@weakify和@strongify
来源:互联网 发布:mysql utf 8 编辑:程序博客网 时间:2024/06/11 09:57
提到OC中的block,它像函数指针,当然了,我们知道OC其实都是结构体,所以也就是结构体指针了,我们暂不讨论LLVM的Clang前端是如何转换OC代码的。
一般来说,引入ARC后,出现内存泄露的情况少很多了,很容易出现的地方还是在于使用block造成的循环引用,即block内捕获了外部实例变量,为了保证block内部变量一直存在,默认对其进行了强引用,如果在这个变量的强引用链上,也引用着该block,那么好了,这些内存就无法被收回了。
解决方案比较简单,如同使用代理一样,其中一方弱引用另一方即可,于是,我们常做的是,在栈上使用临时变量,弱引用那个可能强引用着block的变量,然后在block体内使用这个临时变量,即可打破此强引用循环。这里设及了两个关键字__weak __strong(默认是strong的),在MRC的时候,也有这个问题,那时使用__block来解决,现在MRC过时了,这个也不再提。
我估计大家都用过或者至少也听过,有个FRP(函数响应式编程)的框架ReactiveCocoa Framework.
那我们来看看RAC中的@weakify和@strongify是怎么玩的。
这俩其实就是宏,但我想大家和我一样一开始就觉得这玩意儿前面咋有个@,于是看了看宏定义,差点就喷了
我们展开@weakify
#define weakify(...) \
rac_keywordify \
metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)
这还看不出什么来,展开看rac_keywordify这个宏
#if DEBUG
#define rac_keywordify autoreleasepool {}
#else
#define rac_keywordify try {} @catch (...) {}
#endif
原来那个@是autoreleasepool和try前面的@啊
是的,就是。那么问题来了,为什么要用这个呢?我们看看注释:
// Details about the choice of backing keyword:
//
// The use of @try/@catch/@finally can cause the compiler to suppress
// return-type warnings.
// The use of @autoreleasepool {} is not optimized away by the compiler,
// resulting in superfluous creation of autorelease pools.
//
// Since neither option is perfect, and with no other alternatives, the
// compromise is to use @autorelease in DEBUG builds to maintain compiler
// analysis, and to use @try/@catch otherwise to avoid insertion of unnecessary
// autorelease pools.
各自有各自的问题,要区分DEBUG也是在权衡之下的选择,但用这些的目的其实就是避免出现警告。接下来看metamacro_foreach_cxt
#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \
metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)
这里的metamacro_concat就是将两者连接到一起,而里面还有metamacro_foreach_cxt,ok那这就是递归了。这里不想多做展开,后面metamacro_argcount从名字上看就是取变量个数的,其实连接起来会变成另一个宏,比如metamacro_foreach_cxt0,一系列的定义如下#define metamacro_foreach_cxt0(MACRO, SEP, CONTEXT)
#define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)
.......
这样你就理解了这种递归写法了。我们一般就传一个self,那实际上就是metamacro_foreach_cxt1(rac_weakify_,, __weak, self) => rac_weakify_(0,__weak,self)
我们来看rac_weakify_
#define rac_weakify_(INDEX, CONTEXT, VAR) \
CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR);
那么上面的可以翻译成 __weak __typeof__(self) self_weak_ = (self)
至此,我相信大家就知道了@weakify宏翻译成代码是什么样子了。
那么@strongify定义如下
#define strongify(...) \
rac_keywordify \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
metamacro_foreach(rac_strongify_,, __VA_ARGS__) \
_Pragma("clang diagnostic pop")
可以看到,为了去警告也是用心良苦了。这里面的代码和weak基本上差不多,不过可以发现翻译出来,里面有这个self_weak_,它是有weak定义的,所以,使用strongify的话,前面必须有weakify,而且weakify只能使用一次,多了就重复定义了。
ok , end
- weakify和strongify
- @weakify和@strongify
- @weakify, @strongify
- @weakify, @strongify
- @weakify, @strongify
- MRC/ARC通用的weakify和strongify
- @weakify, @strongify 详解
- @weakify, @strongify 使用
- weakify strongify 实现
- Reactive Cocoa中@weakify和@strongify实现分析
- 文MRC/ARC通用的weakify和strongify
- 剖析RAC中的@weakify、@strongify
- weakify/strongify 大法,的简单宏,抄至于YYKit
- ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify
- ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify
- ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify
- @strongify以及@weakify宏命令的的使用(1)
- ObjC的Block中使用weakSelf/strongSelf @weakify/@strongify
- C++相对路径转换为绝对路径和linux、window移植api
- Sine之舞
- hdu5721Palace
- 源码-PL/SQL从入门到精通-第五章-管理数据表
- CS231n 学习笔记(1)——神经网络 part1 :图像分类与数据驱动方法
- @weakify和@strongify
- openjudge3344 冷血格斗场 解题报告
- 基于openCV实现人脸检测
- 欢迎使用CSDN-markdown编辑器
- Java DB 学习资料
- eclipse导出javadoc遇到的问题
- 设计模式之观察者模式
- 右击/左击treeview,获取树节点
- optee fvp