iOS strong-weak

2017-11-15  本文已影响10人  草原烈鹰

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中场景:

  1. 使用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都不会被释放掉。

  1. 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的不足。

上一篇 下一篇

猜你喜欢

热点阅读