1、应用举例
分别用strong、weak、__unsafe_unretained指针指向对象,观察对象销毁情况:
- (void)viewDidLoad {[super viewDidLoad];__strong Person* person1;__weak Person* person2;__unsafe_unretained Person* person3;NSLog(@"1");{Person *person = [[Person alloc] init];}NSLog(@"2");}
没有指针指向person对象,查看打印结果:
~: 1~: -[Person dealloc]~: 2
person会在第12行代码执行结束后销毁。
使用__strong指针指向Person对象,查看打印结果:
- (void)viewDidLoad {[super viewDidLoad];__strong Person* person1;__weak Person* person2;__unsafe_unretained Person* person3;NSLog(@"1");{Person *person = [[Person alloc] init];person1 = person;}NSLog(@"2");}
~: 1~: 2~: -[Person dealloc]
person会在person1销毁后销毁。
换成person2或者person3指向person对象,查看打印结果:
- (void)viewDidLoad {[super viewDidLoad];__strong Person* person1;__weak Person* person2;__unsafe_unretained Person* person3;NSLog(@"1");{Person *person = [[Person alloc] init];person2 = person;}NSLog(@"2");}
~: 1~: -[Person dealloc]~: 2
person会在第13行代码执行结束后销毁,可以看出弱指针引用不会影响对象的销毁。
weak和unsafe_unretained的区别是weak修饰的指针在被修饰对象销毁时,会自动置为nil,unsafe_unretained则不会,所以__unsafe_unretained是不安全的。
2、weak指针销毁原理
通过查看objc源码:
NSObject.mm
dealloc方法
_objc_rootDealloc方法
objc-object.h
rootDealloc方法
objc-runtime-new.mm
object_dispose方法
objc_destructInstance方法
void *objc_destructInstance(id obj){if (obj) {// Read all of the flags at once for performance.bool cxx = obj->hasCxxDtor();bool assoc = obj->hasAssociatedObjects();// This order is important.// 清除成员变量if (cxx) object_cxxDestruct(obj);// 清除关联对象if (assoc) _object_remove_assocations(obj, /*deallocating*/true);// 将指向当前对象的弱指针置为nilobj->clearDeallocating();}return obj;}
在对象调用dealloc时,会将指向当前对象的弱指针置为nil。
3、总结
weak指针是存储在SideTable里的weak_table中,也是一个哈希表。
struct SideTable {spinlock_t slock;RefcountMap refcnts;weak_table_t weak_table;};
当对象销毁时,会从weak_table中找到指向自己的weak指针,将weak指针置为nil。
