内存管理
- 引用计数:Objective-C Python
- 垃圾收集:C#,Java等
- 区别
内存管理的基本规则
- 自己生成的对象,自己持有
- 非自己生成的对象,自己也能持有
- 不再需要自己持有的对象要释放
- 非自己持有的对象无法释放
自己生成的对象,自己持有
使用以下名称开头的方法名意味着自己生成的对象只能自己持有
- alloc
- new
- copy
- mutableCopy
非自己生成的对象,自己也能持有
通过retain方法,非自己生成的对象跟用alloc/new/copy/mutableCopy方法生成并持有的对象一样,成为自己持有
不再需要自己持有的对象要释放
自己持有的对象,一旦不在需要,持有者有义务释放该对象,使用release方法
使用autorelease推迟对象的释(一般用于返回对象的方法)
非自己持有的对象无法释放
alloc/retain/release/dealloc实现
- alloc -> callAlloc ->class_createInstance -> calloc
- retain -> sidetable_retain(SideTable refcnts ++)
- release -> sidetable_release(objc_msgSend)(this, SEL_dealloc))
- dealloc -> _object_dispose(objc_destructInstance)
autorelease实现
- _objc_autoreleasePoolPush-> ... -> _objc_autoreleasePoolPop
- 在每个runloop开始前,系统会创建一个autoreleasepool,在结束之前drain释放
每一个线程都有一个runloop,每个autoreleasepool对应着一个线程
(使用block枚举时,自动添加autorelease)
什么时候手动添加autoreleasepool
- 编写的程序不是基于UI框架的
- 循坏中创建了大量的临时对象
- 创建一个辅助线程
ARC规则
修饰符
- __strong
- __weak
- __unsafe_unretained
- __autoreleasing
__strong修饰符
- 默认修饰符,表示强引用
__weak修饰符
- __strong容易发生循坏引用,特别是“父-子”关系的对象
- __weak提供若引用,超出作用域会自动设置为nil,避免循坏引用
- 检查附有__weak修饰符的变量是否为nil,判断被赋值的对象是否被废弃
__unsafe_unretained
- 和__weak的区别是不会设置nil,会造成空指针
- 在iOS4兼容
__autoreleasing
- 在ARC有效时,@autoreleaspool代替NSAutoreleasPoll类,__autoreleasing修饰的变量代替autorelea方法
- 访问__weak修饰的变量必须访问注册到autoreleasepool的对象
- id的指针或者对象的指针在没有显示的指定时会被附加上__autoreleasing修饰符(例如:NSError *error)
规则
- 不能使用retain/release/retainCount/autorelease
- 不能使用NSAllocateObject/NSDeallocateObject
- 遵守内存管理的方法命名规则
- 不要显示调用dealloc
- 使用@autoreleasepool块代替NSAutoreleasePool
- 不能使用区域
- 对象型变量不能作为C语言结构体的成员
- 显示转换"id"和“void *”
显示转换"id"和“void *”
- 通过"__bridge"转换,id和“void *”就能相互转换
- __bridge_retained 使要转换赋值变量也持有所赋值的对象
- __bridge_transfer 被转换的变量所持有的对象在该变量被赋值给转换目标变量后随之释放
ARC的实现
__strong修饰符
- objc_storeStrong -> objc_retain,objc_release(prev) -> objc_release(obj)
__weak修饰符
- objc_initWeak-> storeWeak -> objc_destroyWeak -> objc_release
__autoreleasing
- objc_autoreleasePoolPush -> ... -> objc_autorelease -> objc_autoreleasePoolPop
引用计数
- retainCount -> refcnts