ReactiveCocoa中的宏

weakify

源码:

#define weakify(...) \
    autoreleasepool {} \
    metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)

使用方法:

@weakify(anObject);
//展开后
@autoreleasepool{

}
metamacro_foreach_cxt(rac_weakify_,,__weak,__VA_ARGS__)

这里有两个问题:

  • autoreleasepool的作用是什么?
  • metamacro_foreach_cxt干了什么 ?

在使用这两个宏时,为了看起来符合libextobjc的语言习惯,前面会加上@,所以autoreleasepool仅仅是为了配合使用宏的是@符号。

再看后者:

/**
* 对于每个参数,使用MACRO进行处理,然后使用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两个字符串
metamacro_argcount(...) \\返回参数的个数

所以展开后:

@weakify(anObject);
//展开后
@autoreleasepool{

}
metamacro_foreach_cxt1(rac_weakify_,,__weak,__VA_ARGS__)
//继续展开
@autoreleasepool{

}
rac_weakify(0,__weak, anObject)
//rac_weakify展开后
@autoreleasepool{

}
__weak __typeof__(anObject) anObject_weak_ = (anObject)

所以最终weakify定义了一个object_weak_变量,以weak方式引用object。
同样展开strongtify宏之后,其结果是:

__strong __typeof__(anObject) anObject = anObject_weak_

所以是在block中将定义了一个局部变量object指向了object_weak_

RACObserve

定义:

#define RACObserve(TARGET, KEYPATH) \
    [(id)(TARGET) rac_valuesForKeyPath:@keypath(TARGET, KEYPATH) observer:self]

这里看主要是调用了rac_valuesForKeyPath方法,而这个方法的参数使用了另一个宏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的作用就是如果参数数量等于1,就执行keypath1,否则执行keypath2(其实这里metamacro_if_eq的实现方式也值得看一下)。自动提示就是通过OBJ.PATH来做的,keypath2返回的其实就是PATH的字符串形式。

你可能感兴趣的:(ReactiveCocoa中的宏)