@weakify @strongify隔缀。
首先看一下實(shí)現(xiàn)的方式:
方式1: 傳統(tǒng)寫法:
#ifndef weakify
#if __has_feature(objc_arc)
#define weakify( x )
_Pragma("clang diagnostic push")
_Pragma("clang diagnostic ignored "-Wshadow"")
autoreleasepool{} _weak typeof(x) weak##x## = x;
_Pragma("clang diagnostic pop")
#else
#define weakify( x ) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
autoreleasepool{} __block __typeof__(x) __block_##x##__ = x; \
_Pragma("clang diagnostic pop")
#endif
#endif
#ifndef strongify
#if __has_feature(objc_arc)
#define strongify( x ) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
try{} @finally{} __typeof__(x) x = __weak_##x##__; \
_Pragma("clang diagnostic pop")
#else
#define strongify( x ) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
try{} @finally{} __typeof__(x) x = __block_##x##__; \
_Pragma("clang diagnostic pop")
#endif
#endif
第二種: 裝逼寫法: 比如RAC
#define weakify(...)
autoreleasepool {}
metamacro_foreach_cxt(rac_weakify_,, __weak, VA_ARGS)
#define strongify(...) \
try {} @finally {} \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
metamacro_foreach(rac_strongify_,, __VA_ARGS__) \
_Pragma("clang diagnostic pop")
今天, 來解釋一下RAC怎么實(shí)現(xiàn)這種裝逼的寫法。
他們的作用主要是在block內(nèi)部管理對(duì)self的引用:
@weakify(self); // 定義了一個(gè)__weak的self_weak_變量
[RACObserve(self, name) subscribeNext:^(NSString *name) {
@strongify(self); // 局域定義了一個(gè)__strong的self指針指向self_weak
self.outputLabel.text = name;
}];
這個(gè)宏為什么這么吊,前面加@,其實(shí)就是一個(gè)啥都沒干的@autoreleasepool {}
前面的那個(gè)@,為了顯眼罷了。 還有metamacro_foreach_cxt
, 我們一層一層的往里點(diǎn)
第一次:
#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \
metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)
繼續(xù)點(diǎn)下去
#define metamacro_concat(A, B) \
metamacro_concat_(A, B)
接著點(diǎn)
#define metamacro_concat_(A, B) A ## B
到最后, 才tm的發(fā)現(xiàn), 這不就是個(gè)C語言中組合運(yùn)算符的么, 把2個(gè)運(yùn)算符組合成為1個(gè)運(yùn)算符。 然后回過頭看, 他就是把 weak 以及第二步驟中#define rac_weakify_(INDEX, CONTEXT, VAR) \CONTEXT typeof__(VAR) metamacro_concat(VAR, weak) = (VAR);
的typedef拼接進(jìn)去- - , 媽的 這都要裝逼八回。。驾诈。缠诅。
這兩個(gè)宏一定成對(duì)出現(xiàn),先weak再strong.可以很好的管理Block內(nèi)部對(duì)self的引用乍迄。 當(dāng)然你如果是一個(gè)不愛用黃色宏的屌絲的話管引、 你可以用原生代碼寫出來
__weak typeof(self) weakSelf = self;
self.Button.rac_command = [[RACCommand alloc]initWithEnabled:textSig
signalBlock:^RACSignal *(NSString * input) {
__strong typeof(weakSelf) strongSelf = weakSelf;
return nil;
}];
越是細(xì)節(jié)的東西, 越注定成敗。