weakify
源碼:
#define weakify(...) \
autoreleasepool {} \
metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)
使用方法:
@weakify(anObject);
//展開后
@autoreleasepool{
}
metamacro_foreach_cxt(rac_weakify_,,__weak,__VA_ARGS__)
這里有兩個(gè)問題:
- autoreleasepool的作用是什么?
- metamacro_foreach_cxt干了什么 ?
在使用這兩個(gè)宏時(shí),為了看起來符合libextobjc的語言習(xí)慣,前面會加上@,所以autoreleasepool僅僅是為了配合使用宏的是@符號。
再看后者:
/**
* 對于每個(gè)參數(shù),使用MACRO進(jìn)行處理,然后使用SEP分隔
*/
#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \
metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)
其中:
metamacro_concat(A,B) \\拼接A,B兩個(gè)字符串
metamacro_argcount(...) \\返回參數(shù)的個(gè)數(shù)
所以展開后:
@weakify(anObject);
//展開后
@autoreleasepool{
}
metamacro_foreach_cxt1(rac_weakify_,,__weak,__VA_ARGS__)
//繼續(xù)展開
@autoreleasepool{
}
rac_weakify(0,__weak, anObject)
//rac_weakify展開后
@autoreleasepool{
}
__weak __typeof__(anObject) anObject_weak_ = (anObject)
所以最終weakify定義了一個(gè)object_weak_變量,以weak方式引用object。
同樣展開strongtify宏之后,其結(jié)果是:
__strong __typeof__(anObject) anObject = anObject_weak_
所以是在block中將定義了一個(gè)局部變量object指向了object_weak_
RACObserve
定義:
#define RACObserve(TARGET, KEYPATH) \
[(id)(TARGET) rac_valuesForKeyPath:@keypath(TARGET, KEYPATH) observer:self]
這里看主要是調(diào)用了rac_valuesForKeyPath方法,而這個(gè)方法的參數(shù)使用了另一個(gè)宏keypath。
#define keypath(...) \
metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__))(keypath1(__VA_ARGS__))(keypath2(__VA_ARGS__))
#define keypath1(PATH) \
(((void)(NO && ((void)PATH, NO)), strchr(# PATH, '.') + 1))
#define keypath2(OBJ, PATH) \
(((void)(NO && ((void)OBJ.PATH, NO)), # PATH))
metamacro_if_eq的作用就是如果參數(shù)數(shù)量等于1,就執(zhí)行keypath1,否則執(zhí)行keypath2(其實(shí)這里metamacro_if_eq的實(shí)現(xiàn)方式也值得看一下)。自動(dòng)提示就是通過OBJ.PATH來做的,keypath2返回的其實(shí)就是PATH的字符串形式。