IOS面试之什么时候在ObjC的Block中使用weakSelf

2016-12-01  本文已影响33人  子键_北京不眠夜

Objective C 的 Block 是一个很实用的语法,特别是与GCD结合使用,可以很方便地实现并发、异步任务。但是,如果使用不当,Block 也会引起一些循环引用问题(retain cycle)—— Block 会 retain ‘self’,而 ‘self‘ 又 retain 了 Block。因为在 ObjC 中,直接调用一个实例变量,会被编译器处理成 ‘self->theVar’,’self’ 是一个 strong 类型的变量,引用计数会加 1,于是,"self retains queue", "queue retains block","block retains self"。

解除retain cycle

Apple 官方的建议是,传进 Block 之前,把 ‘self’ 转换成 weak automatic 的变量,这样在 Block 中就不会出现对 self 的强引用。如果在 Block 执行完成之前,self 被释放了,weakSelf 也会变为 nil。

__weak __typeof__(self) weakSelf = self;
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     [weakSelf doSomething];
});

在doSomething完成之前,weakSefl不会被释放
但 下面的情况例外

__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    __strong __typeof(self) strongSelf = weakSelf;
   [strongSelf doSomething];
   [strongSelf doOtherThing];
});

在 doSomething 中,weakSelf 不会变成 nil,不过在 doSomething 执行完成,调用第二个方法 doOtherThing 的时候,weakSelf 有可能被释放,于是,strongSelf 就派上用场了:

__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   __strong __typeof(self) strongSelf = weakSelf;
   [strongSelf doSomething];
   [strongSelf doOtherThing];
});

__strong 确保在 Block 内,strongSelf 不会被释放。

总结

是在为了避免在block的执行过程中,突然出现self被释放的尴尬情况。

什么情况下不需要使用weakSelf?

当动画结束时,UIView 会结束持有这个block,如果没有别的对象持有block的话,对象就会释放掉,从而block会释放掉对self的持有。整个内存引用关系被解除。

上一篇 下一篇

猜你喜欢

热点阅读