@weakify, @strongify ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify
首先要说说什么时候使用weakSelf和strongSelf。
下面引用一篇博客《到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf》的内容:
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 __weak __typeof__(self) weakSelf = self;
2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3 [weakSelf doSomething];
4 });
clang 的文档表示,在 doSomething 内,weakSelf 不会被释放。但,下面的情况除外:
1 __weak __typeof__(self) weakSelf = self;
2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3 [weakSelf doSomething];
4 [weakSelf doOtherThing];
5 });
在 doSomething 中,weakSelf 不会变成 nil,不过在 doSomething 执行完成,调用第二个方法 doOtherThing 的时候,weakSelf 有可能被释放,于是,strongSelf 就派上用场了:
1 __weak __typeof__(self) weakSelf = self;
2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3 __strong __typeof(self) strongSelf = weakSelf;
4 [strongSelf doSomething];
5 [strongSelf doOtherThing];
6 });
__strong 确保在 Block 内,strongSelf 不会被释放。
总结
- 在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。
- 如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。
-------------------------------分割线---------------------------------------------
以上内容知道了我们为什么要用weakSelf和strongSelf, 为了简单实用一般会定义成宏weakify和strongify,如下:

1 #ifndef weakify
2 #if __has_feature(objc_arc)
3
4 #define weakify( x ) \
5 _Pragma("clang diagnostic push") \
6 _Pragma("clang diagnostic ignored \"-Wshadow\"") \
7 autoreleasepool{} __weak __typeof__(x) __weak_##x##__ = x; \
8 _Pragma("clang diagnostic pop")
9
10 #else
11
12 #define weakify( x ) \
13 _Pragma("clang diagnostic push") \
14 _Pragma("clang diagnostic ignored \"-Wshadow\"") \
15 autoreleasepool{} __block __typeof__(x) __block_##x##__ = x; \
16 _Pragma("clang diagnostic pop")
17
18 #endif
19 #endif
20
21 #ifndef strongify
22 #if __has_feature(objc_arc)
23
24 #define strongify( x ) \
25 _Pragma("clang diagnostic push") \
26 _Pragma("clang diagnostic ignored \"-Wshadow\"") \
27 try{} @finally{} __typeof__(x) x = __weak_##x##__; \
28 _Pragma("clang diagnostic pop")
29
30 #else
31
32 #define strongify( x ) \
33 _Pragma("clang diagnostic push") \
34 _Pragma("clang diagnostic ignored \"-Wshadow\"") \
35 try{} @finally{} __typeof__(x) x = __block_##x##__; \
36 _Pragma("clang diagnostic pop")
37
38 #endif
39 #endif

使用过RAC的同学应该都知道@weakify和@strongify,这两个宏在RAC中是已经定义好的,可以直接用,属于比较牛逼的写法。这两个宏一定成对出现,先@weakify再@strongify.可以很好的管理Block内部对self的引用。可以一步步点开发现其实使用到了C语言中的组合运算符。
1 @weakify(self);
2 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
3 @strongify(self);
4 [self doSomething];
5 [self doOtherThing];
6 });
@weakify, @strongify ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify的更多相关文章
- ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify
首先要说说什么时候使用weakSelf和strongSelf. 下面引用一篇博客<到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf>的内容: Objec ...
- 到底什么时候才需要在ObjC的Block中使用weakSelf/strongSelf
转载,原文: http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block ...
- iOS Block中的weakSelf/strongSelf
Objective C 的 Block 是一个很实用的语法,特别是与GCD结合使用,可以很方便地实现并发.异步任务.但是,如果使用不当,Block 也会引起一些循环引用问题(retain cycle) ...
- 【转载】在block中使用weakSelf/strongSelf
http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/
- iOS 面试题(二):什么时候在 block 中不需要使用 weakSelf --转自唐巧
问题 我们知道,在使用 block 的时候,为了避免产生循环引用,通常需要使用 weakSelf 与 strongSelf,写下面这样的代码: __weak typeof(self) weakSelf ...
- 关于 Block 中捕获 self 的分析
问题 最近遇到一个已经使用了weak-strong dance的block依旧强引用了self的情况,好在block没被VC持有只是延迟释放,但这里的关键是用了weak_self的blcok理应不会强 ...
- Block中的引用循环
原文地址:http://www.cnblogs.com/lujianwenance/p/5910490.html Block在实际的开发中非常的常用,事件回调.传值.封装成代码块调用等等.很多人都对b ...
- 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)- block中任性用self
前言: 在处理完框架内存泄漏的问题后,见上篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug 发现业务代码有一个地方的内存没释放,原因很也简单: ...
- iOS开发-多层嵌套block中如何使用__weak和__strong
1.关于__weak__weak只能在ARC模式下使用,也只能修饰对象(比如NSString等),不能修饰基本数据类型(比如int等)__weak修饰的对象在block中不可以被重新赋值.__weak ...
随机推荐
- Spring 配置文件详解 (以2.5为例)
转载自:http://blog.csdn.net/zzjjiandan/article/details/22922847 Spring配置文件是用于指导Spring工厂进行Bean生 ...
- val, lazy, def
val strVal = scala.io.Source.fromFile("test.txt").mkString //在strVal被定义的时候获取值,如果test.txt不存 ...
- concat,reverse
1.concat 连接,拼接 <script> var arr1=[1,2,3]; var arr2=[4,5,6]; var arr3=[7,8,9]; alert(arr1.conca ...
- eclipse中如何修改dynamic web module version
java项目中,若切换服务器,经常会涉及到动态web模块版本的问题. 比如:新建了web项目,开始使用tomcat服务器,但是后来使用jboss服务器,就会出现:Project facet ...
- Oracle10g RAC的简单操作
1.查看OCR位置用户指定的位置会被放置在 /etc/oracle/ocr.loc(Liunx系统) 或 /var/opt/oracle/ocr.loc [oracle@rac4 opt]$ cat ...
- java类加载器的层次结构
类加载器的层次结构: 引导类加载器(bootstrap class loader) 用来加载java的核心库(JAVA_HOME/jre/lib/rt.jar,或sun.boot.class.path ...
- 20145334实验三《敏捷开发与XP实践》
实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步骤 1.敏捷开发与XP 敏捷开发(Agile Dev ...
- openstack组件之keystone
一 什么是keystone keystone是 OpenStack Identity Service 的项目名称.它在整个体系中充当一个授权者的角色. Keystone项目的主要目的是给整个opens ...
- js判断移动终端url跳转
CODE <script> //判断终端url跳转 function sp_isMobile() { return Boolean(navigator.userAgent.match(/. ...
- 【转】NGUI研究院之为什么打开界面太慢(十三)
NGUI打开界面太慢了,起初一直以为是unity的问题,最近经过我的全面测试我发现这和unity没有关系.一般一个比较复杂的界面大概需要150个GameObject 或者 UISprite .我用N ...