这是 看 书籍 Objective-C 高级编程 ios与os x多线程和内存管理 一书的随记。
调试
1.查看 autoreleasePool 池里面的对象
extern void _objc_autoreleasePoolPrint();
_objc_autoreleasePoolPrint();
2.通过 clang 可以 查看对应的 汇编代码。其实xcode 的 Product-》Perform Action ->Assemble "" 也就ok了
clang -fobjc-arc -framework Foundation test.m -o test
3 通过 CFGetRetainCount((__bridge CFTypeRef)test2)); 或者
extern uintptr_t _objc_rootRetainCount();
NSLog(@"xxxx %lu",_objc_rootRetainCount(self.array));
可以在 arc 总看到 retaincount 的值。切记 不要依赖这个retaincount 编译器 有很多优化。可能跟你理解的不同。比如 当你 通过一个非 alloc new copy mutableCopy 方法获取一个对象的时候 按照道理是 获取的 autorelease 对象。然后在 retain 。编译器 会优化省略 autorelease 过程。
自己生成的对象,自己所持有
非自己生成的对象,自己也能持有
不在需要自己持有对象时释放
非自己持有的对象 无法释放
方法名称 以 alloc new copy mutableCopy 开头的方法 必须返回给调用者应当持有的对象。
以init 开头的 更加严格 必须返回 id 类型 或者当前类的 类型 或者 子类父类。这个对象不会注册到 autorelease 池里面去。只是
id 类型 和对象类型 默认的修饰符。即:
id xx = [[NSObject alloc] init]; 实际上就等于
id _strong obj = [[NSObject alloc] init ];
简单的说 就是当 strong 修饰符修饰的变量 被赋值的时候。 就相等于 retain 了该对象。 当该修饰符 修饰的变量 抛弃原本指向的对象的时候。 就相当于 release了 该对象。当strong 修饰的变量结束了有效区域的时候。也会release
当2个对象互相引用导致引用环的时候就需要weak了。 简单的说就是赋值的时候 不改变 retainCount的概念。当然还有当对象释放之后 会设置为 nil。这也是 _weak 和 __unsafe_unretain 的主要区别。
这里有个需要注意的。当使用__weak 变量的时候。不是简单的访问。 是会调用一个方法 retainWeakReference (可以重写这个非公开方法 用来调试。但正式开发千万别加逻辑。) 书上说 会加入到 autoreleasePool 里面去。可是访问结束查看 autoreleasePool 。在使用访问 __weak的时候 也确实可以查看到 retainCount 增加了1. 这里可以 猜测 是只是访问的那里新建了一个 autoreleasePool池。访问结束 就 已经释放了。
这样的作用是因为 weak 不持有该对象。当访问过程中。可能被释放掉。 这样就能保证访问过程中都是有效状态。
我能想到的跟 __weak 的区别就是 释放了对象的时候 不设置为 nil。用这个修饰符的对象 不被arc内存管理 所管理。
autorelease 的本质就是 创建一个NsAutoreleasePool 对象。当一个对象调用 autorelease 的时候。 会去获取当前使用的 最内侧(如果有嵌套的池的话)的NsAutoreleasePool对象。然后调用 NsAutoreleasePool对象的一个 类似数组 的addobject 方法。让 NsAutoreleasePool对象来持有这个 autorelease 对象。 当调用 NsAutoreleasePool 的 drain方法的时候。清除引用。 就释放了 autorelease对象。
实际上在arc 中 。编译器有很多优化。让原本是autorelease 的对象 根本就不加入到 NSAutoreleasePool中去。
pd:这里需要注意的是 指针变量 默认的修饰符 是 autoreleaseing 比如 id *xx。 是 autoreleaseing的 而 id xx 是 strong的。
属性 | 修饰符 |
assign | __unsafe_unretained |
copy | __strong(是retain的复制的新对象) |
retain | __strong |
strong | __strong |
unsafe_unretained | __unsafe_unretained |
weak | __weak |
另外这里测试的时候 发现 如果在方法里面 有个 __weak属性 每次使用 属性都会导致retainCount +1. 查看汇编代码 有个
_objc_retainAutoreleasedReturnValue 方法被调用了。完全不知道为什么。。
看了下 _objc_autoreleasedReturnValue 函数 返回 注册到 autoreleasepool 里面的对象。 但是 跟 autorelease 函数又不同。 如果 _objc_autoreleasedReturnValue 方法之后 会立即调用 _objc_retainAutoreleasedReturnValue 就不将对象注册到 autoreleasepool 中。而是直接传递到方法或者函数的调用方。 _objc_retainAutoreleasedReturnValue 和 objc_retain 函数不同。 这个作用 就是 上面说到的。 对于不是 new alloc copy mutablecopy 开头的方法。按道理返回的对象是 autorelease 然后在retain 。这个机制就优化了这里的代码