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 circle

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

示例代码:

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

clang 的文档表示,在 doSomething 内,weakSelf 不会被释放。但,下面的情况除外:

1
2
3
4
5
__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomething];
[weakSelf doOtherThing];
});

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

1
2
3
4
5
6
__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。
  • 如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。

参考

原文作者: lslin
原文链接: http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/
版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0

iOS Block中的weakSelf/strongSelf的更多相关文章

  1. @weakify, @strongify ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify

    首先要说说什么时候使用weakSelf和strongSelf. 下面引用一篇博客<到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf>的内容: Objec ...

  2. ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify

    首先要说说什么时候使用weakSelf和strongSelf. 下面引用一篇博客<到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf>的内容: Objec ...

  3. 到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf

    转载,原文: http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block ...

  4. 【转载】在block中使用weakSelf/strongSelf

    http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/

  5. ios block中引用self

    __block __weak typeof(self) tmpSelf = self; ^(){ tmpSelf...... }

  6. iOS block 的底层实现

    其实swift 的闭包跟 OC的block 是一样一样的,学会了block,你swift里边的闭包就会无师自通. 参考:http://www.jianshu.com/p/e23078c11518 ht ...

  7. iOS 面试题(二):什么时候在 block 中不需要使用 weakSelf --转自唐巧

    问题 我们知道,在使用 block 的时候,为了避免产生循环引用,通常需要使用 weakSelf 与 strongSelf,写下面这样的代码: __weak typeof(self) weakSelf ...

  8. 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)- block中任性用self

    前言: 在处理完框架内存泄漏的问题后,见上篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug 发现业务代码有一个地方的内存没释放,原因很也简单: ...

  9. iOS __weak __strong WeakSelf StrongSelf

    在block中常常会用到self,可是会造成循环引用.这时候就需要这样来解决这个问题: #define WeakSelf __weak typeof(self) weakSelf = self #de ...

随机推荐

  1. 如何设置MySQL Workbench EER Diagram 尺寸?

    ER Diagram -> Model -> Diagram Properties and Size...

  2. 那些常用的eclipse快捷键

    用了很久的eclipse了,有些快捷键常用,有的偶尔使用,现在记下常用的快捷键,以便大家和自己查用(持续更新) 这些快捷键都可以在[window]-[preferences]-[general]-[k ...

  3. C++中extern关键字使用(转)

    参考文章:http://blog.csdn.net/sruru/article/details/7951019 chapter1.如何混合编译C语言和C++ 实际开发过程中,C++中会调用C与语言编写 ...

  4. jQuery慢慢啃之文档处理(五)

    1.append(content|fn)//向每个匹配的元素内部追加内容. $("p").append("<b>Hello</b>"); ...

  5. How far away ?

    #include<iostream> #include <algorithm> using namespace std; const int M=40010; int dis[ ...

  6. date日期比较和格式化方法

    时间的比较 var now = new Date();//现在时间 var setDate = new Date(2017,0,5,17,55,55);//设定的时间 laert(now < s ...

  7. JavaScript 继承机制小记

    读<JavaScript: the good parts>, 关于对象继承这块小记一笔: function Base(v){ this.baseValue = v; this.getBas ...

  8. PHP常用代码:

    1.$array=explode(separator,$string); //字符串->数组 2.$string=implode(glue,$array);//数组->字符串 3.file ...

  9. PHP面向对象(OOP):PHP5接口技术(interface)

    PHP与大多数面向对象编程语言一样,不支持多重继承.也就是说每个类只能继承一个父类.为了解决这个问题,PHP引入了接口,接口的思想是指定了一个实现了该接口的类必须实现的一系列方法.接口是一种特殊的抽象 ...

  10. Connect mysql on Linux from Windows

    ON LINUX: 1 sudo apt-get install mysql-server 2 sudo apt-get install python-dev 3 sudo apt-get insta ...