iOS strong-weak
strong-weak dance
平常我们用:
__weak typeof(self) __weakself = self;
__strong typeof(self) __strongself= __weakself;
也就是所谓的:
define MMWeakify(o) __weak typeof(self) mmwo = o;
define MMStrongify(o) __strong typeof(self) o = mmwo;
以为这样,都可以万无一失了,这是不对的。
大概代码:
TT0ViewController.m
NSLog(@"wgj_strongweakself");
self.sself = [strongweakself new];
[self.sself test];
// strongweakself *sself = [strongweakself new];
// [sself test];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"self.block被释放!");
self.sself = nil;
// NSLog(@"ssssss_%@",sself);
});
strongweakself.m
- (void)test{
self.myobject = [TestObject new];
__weak typeof(self) __weakself = self;
// MMWeakify(self);
[self.myobject setWeakblock:^{
NSLog(@"调用block!");
__strong typeof(self) __strongself= __weakself;
// MMStrongify(self);
[__strongself doSomething];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[__strongself doAnotherThing];
});
}];
self.myobject.weakblock();
//下面就是执行之前被销毁,并且用的是转换过的__strong self
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// __strong typeof(self) __strongself= __weakself;
// NSLog(@"%@",__strongself);
// __strongself.myobject.weakblock();
//
//// NSLog(@"%@",self);
//// self.myobject.weakblock();
//
//// __strong typeof(self) __strongself= __weakself;
//// MMStrongify(self);
//// NSLog(@"%@",(self));
//// (self).myobject.weakblock();
// });
}
-(void)doSomething
{
NSLog(@"%s",__func__);
}
-(void)doAnotherThing
{
NSLog(@"%s",__func__);
}
-(void)dealloc{
NSLog(@"%s",__func__);
}
TestObject
@property (nonatomic, copy) void(^weakblock)(void);
strong-weak dance 这是我们最常用的是一种方案,因为block创建时捕获的是weakself,所以block执行之前不能够控制self的生命周期,所以这样不会导致整个block对self进行强引用。之后在block内部创建一个对self进行retain的变量strongself,strongself 作为局部变量强引用了 self 并且会在block执行完毕的时候被自动销毁,这样既可以保证在block执行期间 self 不会被外界干掉,同时也解决了retain cycle的问题。
strong-weak dance 不能解决block执行前,self被释放的问题,我们平时一直使用的strong-weak dance也只能解决block得到调用之后self不被释放的问题。
总结
通过上面几个小例子可以看出来:strong-weak dance确实是比较好的解决方案,但是也不是万能的,他不能解决block调用之前self被释放的问题,下面将block中引用self分为4中场景:
- 使用self
当self不持有、不间接持有block时,可以在block内部直接引用self。
2.使用weakself
当self持有或间接持有block,可以通过在外部创建self的弱引用weakself然后捕获到block内部进行使用,但是这样使用存在一定风险,一般也不推荐使用。
3.使用strong-weak dance
当self持有或间接持有block,此时要使用strong-weak dance。
这种方法也不是万能的,在block被执行前,block对self依然只是弱引用,进入block里面才会retain一次,保证在block执行期间self都不会被释放掉。
- block中强引用self并且打破retain cycle
不管是weakself还是strong-weak dance,目的都是避免retain cycle,strong-weak dance的本质也是在block中搞了一个局部变量来打破这种循环引用的;
如果我们在block中直接使用self,并且在适当的时机打破这种循环(比如说在block执行完成将这个block销毁)也可以避免retain cycle,并且这种在block创建时就强引用的方式,在block被调用前 self 不会被释放掉,可以弥补strong-weak dance的不足。