美文网首页iOS开发
iOS Block循环引用的个人看法

iOS Block循环引用的个人看法

作者: JohnnyB0Y | 来源:发表于2017-03-09 16:12 被阅读52次

    当 Block 直接或间接的被当前对象持有时,如果 Block 也强引用当前对象,就会造成循环引用。

    解决方案一:让 Block 捕获弱引用的 self。

    __weak typeof(self) weakSelf = self;
    
    self.myBlock = ^(NSUInteger index) {
        [weakSelf doSomething:index];
    }
    

    解决方案二:把 self 当参数传进去。

    @property (nonatomic, copy) void(^myBlock)(__kindof AGStudentModel *selfRef);
    
    AGStudentModel *sm = [AGStudentModel new];
    sm.myBlock = ^(AGStudentModel *sm) {
        [sm doSomething];
    };
    
    sm.myBlock(sm);
    

    解决方案三:在 Block 使用完后把对象持有 Block属性制空。
    《Effective Objective-C 2.0》讲到的从内部打破循环引用。

    AGStudentModel *sm = [AGStudentModel new];
    sm.myBlock = ^(int index) {
        sm.name = @"kobe";
        // 制空 block
        sm.myBlock = nil;
    };
    sm.myBlock(24);
    
    或---者
    
    AGStudentModel *sm = [AGStudentModel new];
    __block AGStudentModel *blockSelf = sm;
    sm.myBlock = ^(int index) {
        blockSelf.name = @"kobe";
        // 制空 blockSelf
        blockSelf = nil;
    };
    sm.myBlock(24);
    
    个人看法:
    第一种方案:

    用的比较多,缺点是用的时候代码多,其实 Block 内部使用 self 时还是要强引用回来,这样比较安全。而且代码看起来比较乱。

    第二种方案:

    比较直接,就是设计 Block 时要写多一个参数。不管是调用方还是设计方,使用起来都很方便,代码干净。不过对于间接的循环引用问题比较棘手,设成接收 id 类型,然后还要类型转换。

    第三种方案:

    比较有思想,帮循环引用问题解决在了内部。可是调用方不能直观地知道你是这样设计的。其次就是我用属性保存是持有的性质,怎么用完一次就释放?多次调用还会引起奔溃或self值为nil,感觉不太理想。可能特殊情况会比较适合,例如网络模块设计。

    我个人比较偏向第二种。
    • 理由一,不用写过多代码。
    • 理由二,代码写起来一块一块的,这才是代码块嘛。
    • 理由三,调用方一看就知道干啥,方便又安全。

    相关文章

      网友评论

        本文标题:iOS Block循环引用的个人看法

        本文链接:https://www.haomeiwen.com/subject/kxgwgttx.html