Objective-C weak 指针作用与实现原理

objc4 runtime zeroing weak SideTable weak_table_t Objective-C weak 指针:作用与实现原理 __weak 的核心价值是“引用对象但不拥有对象”:它不会增加引用计数;当对象开始销毁时,runtime 会把所有指向它的 weak 槽位自动写成 nil,避免野指针。这一页按 objc4 源码中的真实路径解释它如何登记、读取、搬迁和清零。 阅读顺序 weak 解决什么问题 运行时数据模型 核心类型、字段、方法 关键操作流程 带注释源码片段 一遍记住 1. weak 的作用 不拥有对象__weak id x = obj; 不会 retain obj,所以不会延长对象生命周期。 自动归零对象销毁时,所有保存该对象地址的 weak 变量会被 runtime 写成 nil。 读时短暂保活读取 weak 时,runtime 会先尝试 retain,再 autorelease,保证表达式使用期间对象不被并发释放。 拒绝无效目标目标正在 dealloc 或类不支持 weak 时,形成 weak 引用会失败或崩溃,取决于入口函数。 **一句话模型:**strong 指针管“拥有关系”,weak 指针管“可观察关系”。delegate、反向引用、缓存回调对象通常适合 weak,因为它们不应该阻止真实所有者释放对象。 2. 运行时数据模型 weak 表不是全局一把大表直接裸用,而是挂在分片的 SideTable 上。runtime 用对象地址选择某个 SideTable,在该表内维护引用计数辅助信息和 weak 表,并用同一把锁保护它们。 ...

June 1, 2026

objc4 Autorelease 一页讲透

objc4 runtime guide Autorelease 的作用和实现原理 一句话:autorelease 是“延迟一次 release”的机制。对象先被登记到当前线程的自动释放池中, 等池子 pop 时再统一发送 release,从而让返回值和临时对象可以跨过当前语句或当前函数继续存活一小段时间。 核心文件:runtime/NSObject.mm 数据结构:AutoreleasePoolPage 线程隔离:TLS hot page 边界标记:POOL_BOUNDARY 先建立正确心智模型 autorelease pool 不是一堆对象的容器类。 在 objc4 里,它更像每个线程私有的一条栈。栈里放两类指针: 普通对象指针,以及表示池边界的 POOL_BOUNDARY。每次 push 池,就压入一个边界并返回这个边界地址作为 token。 每次 autorelease 对象,就把对象指针压到 hot page 的 next 位置。pop 时拿 token 找到边界, 把边界之上的对象按后进先出的顺序逐个 objc_release。 它解决什么问题 **返回 +0 对象:**被调用方可以返回一个“当前调用者可用,但不归调用者拥有”的对象。 **批量释放临时对象:**循环、事件回调、线程入口可以用池边界控制临时对象峰值。 兼容手动引用计数:retain 表示拿所有权,release 表示交回所有权,autorelease 表示稍后自动交回。 **配合 ARC 优化:**运行时和编译器会尝试消除返回值中的多余 retain/autorelease。 一张图看懂栈变化 假设外层池中 autorelease 了 A,又进入内层池 autorelease 了 B、C。内层 pop 只释放 B、C,不影响外层 A。 push 外层 ...

June 1, 2026

Objective-C 关联对象 Associated Objects 作用与实现原理

objc4 runtime Associated Objects objc-references.mm 关联对象 Associated Objects 作用与实现原理 关联对象让调用方在不改类布局、不新增 ivar 的情况下,把一组 key - value 挂到任意 Objective-C 对象上。 objc4 的实现不是把字段塞进对象内存,而是用一张运行时全局表保存“对象地址、key、关联值和内存管理策略”的映射。 入口 APIobjc_setAssociatedObject objc_getAssociatedObject 核心存储AssociationsHashMap ObjectAssociationMap 值封装ObjcAssociation policy + value 清理时机objc_destructInstance objc_disposeClassPair 目录 作用与使用边界 公开 API 与 policy 核心结构与字段 set / get / remove 流程 对象销毁与特殊关联 禁止关联对象的场景 测试覆盖点 作用与使用边界 关联对象主要服务于分类、框架扩展、运行时补充状态等场景:调用方只有对象指针和一个稳定 key,就能为对象保存额外值。 这避免了修改类的 ivar 布局,也让分类可以模拟“存储属性”。 适合做什么 给现有类或分类补充少量状态。 把辅助对象、回调 block、缓存值挂到宿主对象。 用唯一地址作为 key,避免和其他调用方冲突。 不适合做什么 高频读写的核心数据结构。 需要类型系统和对象布局明确表达的状态。 清空他人关联值,尤其是随意调用 objc_removeAssociatedObjects。 运行时代价 每次访问都需要全局关联表查询。 set / get / remove 通过 AssociationsManagerLock 串行保护表。 对象析构时可能需要额外释放所有关联值。 **关键结论:**关联对象是“外置 side table”,不是对象内的 ivar。对象只保存一个“可能有 associated objects”的快速标记,真正的 key/value 在全局表里。 ...

June 1, 2026

Objective-C KVC 作用与实现原理

Key-Value Coding / Foundation behavior with objc4 runtime support Objective-C KVC:从字符串 key 到对象读写 KVC 的核心价值是:把“访问某个属性或实例变量”抽象成 valueForKey:、setValue:forKey: 这样的字符串协议。 读完这一页,你应该能说清楚它解决什么问题、Foundation 大致怎样查找成员, 以及 objc4 runtime 在消息发送、元数据查询、ivar 直写和内存管理上提供了哪些支撑。 适合第一次系统理解 KVC 标注 objc4 / Foundation 边界 含关键流程和注释代码 目录 KVC 到底有什么用 本仓库能看到什么 读写 key 的查找顺序 objc4 提供的底层能力 核心类、方法和关键属性 关键操作流程 常见坑与记忆模型 1. KVC 到底有什么用 平时你写 person.name 或 [person name],访问目标在编译期就固定了。 KVC 允许你在运行时才决定要访问哪个成员:[person valueForKey:@"name"]。 这使得对象、字典、表单、序列化、绑定和调试工具可以用同一套字符串 key 访问模型对象。 动态访问 运行时才知道字段名时,用字符串 key 读取或写入对象。 统一映射 JSON、表单、数据库行、UI 绑定都可以映射到对象属性。 批量和路径 valueForKeyPath: 能沿着 department.manager.name 连续取值。 ...

June 1, 2026

Objective-C KVO 作用与实现原理

objc4 runtime reading note KVO:从“属性变化通知”到 runtime 动态子类 KVO(Key-Value Observing)让一个对象在另一个对象的某个 key path 变化时收到回调。 在这个 objc4 仓库里,Foundation 的 KVO 主体代码不在源码中;但 runtime 暴露了 KVO 需要的关键能力: 复制类、切换对象的 isa、判断 ivar 内存语义,并保证这些操作在初始化、弱引用和并发加载场景下安全。 入口:addObserver 核心:动态子类 通知:will/didChange 底层:objc_duplicateClass 阅读路线 KVO 解决什么问题 实现原理总览 objc4 中的关键支撑 核心类和关键方法 关键流程 带注释代码片段 使用边界和排错 1. KVO 的作用:把“状态变化”变成可订阅事件 普通属性赋值只改变对象内部状态,调用者不知道“谁关心这个变化”。KVO 把某个 key path 的变化包装成标准事件: 被观察对象负责发出变化,观察者在 observeValueForKeyPath:ofObject:change:context: 中接收。 解耦 观察者不需要改写被观察对象的业务代码,只注册感兴趣的 key path。 统一格式 变化以 change 字典传递,可包含旧值、新值、变化类型等。 自动拦截 对 KVC/KVO 兼容的 setter,Foundation 可自动在 setter 前后发通知。 手动通知 复杂派生属性或批量变化可用 willChangeValueForKey: 和 didChangeValueForKey: 明确包围。 ...

June 1, 2026

runtime/hashtable2.mm 作用与实现原理

objc4 runtime NXHashTable 集合结构 runtime/hashtable2.mm 作用与实现原理 这个文件实现了旧 NeXT/Objective-C runtime 暴露的 NXHashTable:一个可存放任意指针或整数数据的哈希集合。它不保存 key-value 对;需要映射关系时,runtime 另用 maptable.mm 的 NXMapTable。 一遍读懂 它用 callback 决定“怎么 hash、怎么判等、怎么释放”。 每个 bucket 是一条很短的冲突链。 bucket 中只有 1 个元素时直接存指针,避免额外分配。 元素数超过 bucket 数时扩容并重算位置。 删除会把 2 个元素的 bucket 收缩回单指针形态。 1. 它解决什么问题 NXHashTable 是 runtime 内部和兼容 API 使用的通用集合容器。调用者传入一组 NXHashTablePrototype,告诉表如何处理元素:hash(info, data) 计算哈希,isEqual(info, a, b) 判断相等,free(info, data) 在销毁或 reset 时释放元素。这样同一套表结构可以存指针、字符串,或“结构体首字段作为 key”的对象。 **关键不变量:**如果两个元素被 isEqual 判为相等,它们的 hash 必须一致;而且参与 hash 的内容不能在入表后变化。否则扩容重排后会找不到元素。 2. 数据结构:一层数组 + 小冲突链 NXHashTable保存 prototype、元素总数、bucket 数组和可透传给 callback 的 info。 ...

June 1, 2026

runtime/maptable.h 作用与实现原理

objc4 runtime NXMapTable 开放寻址哈希表 runtime/maptable.h runtime/maptable.h 作用与实现原理 runtime/maptable.h 定义了 Objective-C runtime 里旧 NeXT 风格的 NXMapTable:一个通用的 key - value 指针映射表。 它不拥有业务对象,只负责把指针或整数形式的 key 映射到指针或整数形式的 value, 并通过回调把“怎么 hash、怎么比较、释放时怎么处理”交给调用方决定。 存储模型连续桶数组,每个桶是 {key, value}。 冲突处理开放寻址 + 线性探测。 扩容阈值元素数超过桶数的 75% 后翻倍重哈希。 runtime 用途类名表、协议表、future class 表、少量 meta 到 non-meta 映射。 阅读路径 它解决什么问题 和 hashtable2 的区别 核心数据结构 Prototype 回调机制 查找、插入、删除、扩容流程 带注释核心代码 runtime 中的实际使用 必须记住的约束 1. 它解决什么问题 runtime 需要维护很多“名字到结构体指针”“元类到类”“未来会出现的类名到占位 Class”的映射。 这些映射发生在启动、加载镜像、注册类、查找协议等低层路径上,不能依赖 Objective-C 容器对象。 NXMapTable 就是一个 C 接口的轻量哈希表。 它是什么 一个 void * key 到 void * value 的映射表。key 和 value 可以是指针,也可以把整数强转成指针使用。 ...

June 1, 2026