美文网首页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