weak基本用法
weak 关键字的作用弱引用,所引用对象的计数器不会加一,使得指针的访问是安全的;并在引用对象被释放的时候自动被设置为 nil
weak 的常见场景是在delegate,block,NSTimer中使用,以避免循环引用所带来的内存泄漏。
weak原理
weak表其实是一个哈希表,key是所指对象的指针,value是weak指针的地址数组。(value是数组的原因是:因为一个对象可能被多个弱引用指针指向) Runtime维护了一张weak表,用来存储某个对象的所有的weak指针。
weak原理实现过程:
1.初始化开始时,会调用objc_initWeak函数,初始化新的weak指针指向对象的地址
2.objc_initWeak函数里面会调用objc_storeWeak() 函数,objc_storeWeak() 函数的作用是用来更新指针的指向,创建弱引用表。
3.在最后会调用clearDeallocating函数。而clearDeallocating函数首先根据对象的地址获取weak指针地址的数组,然后紧接着遍历这个数组,将其中的数组开始置为nil,把这个entry从weak表中删除,最后一步清理对象的记录。
weak释放过程:
1、调用objc_release
2、因为对象的引用计数为0,所以执行dealloc
3、在dealloc中,调用了_objc_rootDealloc函数
4、在_objc_rootDealloc中,调用了object_dispose函数
5、调用objc_destructInstance
6、最后调用objc_clear_deallocating,详细过程如下:
a. 从weak表中获取废弃对象的地址为键值的记录
b. 将包含在记录中的所有附有 weak修饰符变量的地址,赋值为 nil
c. 将weak表中该记录删除
d. 从引用计数表中删除废弃对象的地址为键值的记录
拓展
weak,__unsafe_unretained, unowned 与 assign区别
__unsafe_unretained: 不会对对象进行retain,当对象销毁时,会依然指向之前的内存空间(野指针)
weak: 不会对对象进行retain,当对象销毁时,会自动指向nil
assign: 实质与__unsafe_unretained等同
unsafe_unretained也可以修饰代表简单数据类型的property,weak也不能修饰用来代表简单数据类型的property。
__unsafe_unretained 与 weak 比较,使用 weak 是有代价的,因为通过上面的原理可知,__weak需要检查对象是否已经消亡,而为了知道是否已经消亡,自然也需要一些信息去跟踪对象的使用情况。也正因此,__unsafe_unretained 比 __weak快,所以当明确知道对象的生命期时,选择__unsafe_unretained 会有一些性能提升,这种性能提升是很微小的。但当很清楚的情况下,__unsafe_unretained 也是安全的,自然能快一点是一点。而当情况不确定的时候,应该优先选用 __weak 。
unowned使用在Swift中,也会分 weak 和 unowned。unowned 的含义跟 __unsafe_unretained 差不多。假如很明确的知道对象的生命期,也可以选择 unowned。
weak应用
NSTimer 强引用
开启定时器后,testTimer方法将会一直运行,造成强引用。其中self变为weakSelf,并不能解决强引用,因为NSTimer的内部会对当前的weakSelf引用计数+1
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(testTimerDeallo) userInfo:nil repeats:YES];
/** 方法一直执行 */
-(void)testTimer{
NSLog(@"-----");
}
解决方法:使用block
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakSelf fire];
}];
资料:segmentfault.com/a/119000001…
block
有意思的就在这里,IOS中,block内部,对弱应用的强引用,不会影响对象在外部的释放,同时,保证内部该对象也不会被提前释放。
__weak __typeof(self) weakSelf = self;
// block 内部
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) { return; }
weak singleton
此单例创建的强引用被销毁后,单例被销毁
+ (id)sharedInstance{
static __weak ASingletonClass *instance;
ASingletonClass *strongInstance = instance;
@synchronized(self) {
if (strongInstance == nil) {
strongInstance = [[[self class] alloc] init];
instance = strongInstance;
}
}
return strongInstance;
}