1、实例
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//情况1
__strong Person *person1;
//情况2
__weak Person *person2;
//情况3
__unsafe_unretained Person *person3;
NSLog(@"1");
{
Person *person = [[Person alloc] init];
person.age = 10;
person1 = person;//分别用person1、person2、person3
}
NSLog(@"2");
NSLog(@"3 person = %@",person1);//分别用person1、person2、person3
}
@end
打印结果:
==========================================
情况1:person1
1
2
3 person = <Person: 0x280550ac0>
person dealloc
==========================================
情况2:person2
1
person dealloc
2
3 person = (null)
==========================================
情况3:person3
1
person dealloc
2
崩溃
从结果可以看出,
- 使用__strong修饰person1对象(创建对象默认被Strong修饰),要等到离开viewDidLoad方法后person才会被释放,是因为对person产生了强引用;
- 使用__weak修饰person2对象,等离开person作用域就会被释放,是因为用__weak修饰对象并不会对person产生强引用,而且在person销毁时,person2对象会将自身指针里指向的值置空;
- 使用__unsafe_unretained修饰person3对象,等离开person作用域就会被释放,但是person销毁时,person3不会置空自身指针所指的内容,所以在后来调用的时候就会报错。
2、weak指针原理
在上篇文章学习引用计数的时候,我们已经了解到有SideTable这样的一个结构:![](https://img.haomeiwen.com/i2709914/870ab3011740da9c.png)
其中的refcnts存贮着引用计数,weak_table则存贮这个对象的所有weak指针。
weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。
分析源码,weak 的实现原理可以概括一下三步:
- 1、初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。
- 2、添加引用时:objc_initWeak函数会调用 objc_storeWeak() 函数, objc_storeWeak() 的作用是更新指针指向,创建对应的弱引用表。
- 3、释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry(入口)从weak表中删除,最后清理对象的记录。
3、总结
-
<1>weak指针的实现原理
一个对象对应的isa结构中含有weak_table这样的一个散列表。里面存贮这该对象对应的弱引用指针。当对象要销毁时,取出当前对象对应的弱引用表,把表中存贮内容清除掉,这就是weak指针实现的原理与过程。
网友评论