美文网首页
跳出 Block 的坑 --- weak-strong danc

跳出 Block 的坑 --- weak-strong danc

作者: 47号同学 | 来源:发表于2016-10-28 20:14 被阅读32次

    跳出 Block 的坑

    使用过 Block 的开发者都有一个意识就是,要防止 retain cycel(循环引用)。如何防止 retain cycle 也有很多文章描述过了,但是你的做法真的是安全的吗?下面我们来探究一下 weak-strong dance.

    下面来看一下代码:

    - (void)blockRetainCycleProblem {
        self.block = ^{
            NSLog(@"%@", @[self]);
        };
    }
    

    上面一段代码很明显就是出现了 retain cycel,于是你的解决办法就是如下了:

    - (void)blockRetainCycleProblemAnswer0 {
        __weak typeof(self) weakSelf;
        self.block = ^{
            NSLog(@"%@", @[weakSelf]);
        };
    }
    

    上面的解决方案真的安全吗?

    如果在 block 执行之前,self 被主线程释放掉了,而 weakself 却是对 self 的弱引用,所以根据 ARC 的规则,weakself 会被赋值为 nil(不明白为何为 nil ,可以点击这里)。当 weakself 为 nil,block 中执行的代码就会导致程序 crash。

    于是,又出现下面这种解决方式:

    - (void)blockRetainCycleProblemAnswer1 {
        __weak typeof(self) weakSelf;
        self.block = ^{
            __strong  typeof(weakSelf) strongSelf = weakSelf;
            NSLog(@"%@", @[strongSelf]);
        };
    }
    

    为什么上面这种做法可以防止程序 crash 呢?

    因为 strongSelf 强引用了一次 self ,这时候 self 的 retainCount 为2,即是 self 超出了作用域,引用它的还有 strongSelf 对象,其 retainCount 依然是1,对象还未被释放,依然存在。

    更安全的解决方式如下:

    - (void)blockRetainCycleProblemAnswer2 {
        __weak typeof(self) weakSelf;
        self.block = ^{
            __strong typeof(weakSelf) strongSelf = weakSelf;
            if (strongSelf) {
                NSLog(@"%@", @[strongSelf]);
            }
        };
    }
    

    防止 strongSelf 被释放,而执行相关操作,导致程序 crash.

    相关文章

      网友评论

          本文标题:跳出 Block 的坑 --- weak-strong danc

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