__weak 依赖于 Objective-C 运行时函数 objc_loadWeak。来自Clang 3.4 文档中的Objective-C 自动引用计数:
id objc_loadWeak(id *object);
前提条件:对象是一个有效的指针,它要么包含空指针,要么已注册为__weak对象。
如果object注册为__weak对象,并且存储在object中的最后一个值尚未被释放或开始释放,则保留并自动释放该值并返回它。否则返回 null。相当于下面的代码:
id objc_loadWeak(id *object) {
return objc_autorelease(objc_loadWeakRetained(object));
}
就object上的objc_storeWeak调用而言,必须是原子的。
基本原理
在没有保留的情况下加载弱引用本来就容易出现竞争条件。
由于 objc_loadWeak 需要一个自动释放池,所以在使用 __weak 时必须有一个自动释放池。池可以由 NSAutoreleasePool 或 @autoreleasepool 创建。如果不存在自动释放池,则在 objc_loadWeak 保留它之后不会释放您的对象,因此您的对象将永远不会被释放。
这是上面代码的修复:
#import <Foundation/Foundation.h>
@interface MyObj : NSObject
@end
@implementation MyObj
- (void)dealloc
{
NSLog(@"MyObj dealloc'd %p", self);
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
MyObj* obj1 = [[MyObj alloc] init];
__weak MyObj* weakObj1 = obj1;
NSLog(@"Use it: %p\n", weakObj1);
// Now MyObj is deallocated
}
return 0;
}