RAC的@weakify和@strongify

在使用RAC的代码中看到@weakify和@strongify的使用,第一感觉应该是 __weak和__strong的使用,于是就看了一下,关于这两者的定义:

@weakify:


#define weakify(...) \

rac_keywordify \

metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)


在@weakify的定义的注释中是这么写的:Creates \c __weak shadow variables for each of the variables provided as  arguments, which can later be made strong again with #strongify.

创建一个weak的变量引用作为参数提供给每一个需要调用的地方,之后能够再一次变成strong 通过strongify的方式。

那接下来就看一下weakify 的定义:

metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)


#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \

metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)


其中的(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)这部分是参数,我们之后再来看,先看metamacro_concat 这个的定义:

metamacro_concat:


#define metamacro_concat(A, B) \

metamacro_concat_(A, B)


接下来是metamacro_concat_ 这个函数的定义:

metamacro_concat_:


#define metamacro_concat_(A, B) A ## B


这个函数首先要认清运算符 “##” ,这里是连字符的意思,就是A ## B == AB


那么倒推到上面的的宏定义就变成:


#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \

(metamacro_foreach_cxt ## metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__) 


接下来就需要先看这个metamacro_argcount:,之后后面需要连接的参数是什么。

metamacro_argcount:返回参数的个数


* Returns the number of arguments (up to twenty) provided to the macro. At least one argument must be provided.

#define metamacro_argcount(...) \

metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)


通过函数的注释可以看出:这个函数返回的是参数的个数,为了验证那么需要继续看定义这个宏的其它的宏metamacro_at的定义:


/**

* Returns the Nth variadic argument (starting from zero). At least

* N + 1 variadic arguments must be given. N must be between zero and twenty,

* inclusive.

*/

#define metamacro_at(N, ...) \

metamacro_concat(metamacro_at, N)(__VA_ARGS__)


通过宏的注释可以得到:返回N个可辨的参数,至少需要给出N+1 个可变的参数,而且N必须在0到20之间。

所以上面的:

metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)就变成了metamacro_at20( __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)的样子。

然后看函数metamacro_at20 的定义:


#define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) metamacro_head(__VA_ARGS__)


这时需要看metamacro_head 的定义:


#define metamacro_head(...) \

metamacro_head_(__VA_ARGS__, 0)


根据定义的注释:* Returns the first argument given. At least one argument must be provided.

可以得知,返回第一个参数,而且至少需要一个参数。

进一步去看宏定义metamacro_head_,


#define metamacro_head_(FIRST, ...) FIRST


那么就可以知道此时的metamacro_head返回的是参数列表的第一个参数。

那么之前的宏的定义:

metamacro_at20( __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)返回的是参数列表中参数的个数,就是__VA_ARGS__参数的个数。

也就是metamacro_at20 返回的是N,而N是__VA_ARGS__的个数。

于是最上面的:metamacro_argcount(__VA_ARGS__) 就变成了metamacro_at20( __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1),所以:


(metamacro_foreach_cxt ## metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)=======>>>>

(metamacro_foreach_cxt ## metamacro_at20( __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))(MACRO, SEP, CONTEXT, __VA_ARGS__)=======>>>>

(metamacro_foreach_cxt ## N)(MACRO, SEP, CONTEXT, __VA_ARGS__)


假如此时传入的是self的话那么此时就会变成:

metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, __VA_ARGS__)这样,也就是weakify(...) 转换后的形式。

那就看一下metamacro_foreach_cxt1 的宏定义:


#define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)


而我们在定义weakify的时候传递的参数是:

#define weakify(...) \

rac_keywordify \

metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)

所以我们的参数是:rac_weakify_,, __weak, __VA_ARGS__


metamacro_foreach_cxt1(rac_weakify_,, __weak, __VA_ARGS__)rac_weakify_(0,__weak ,__VA_ARGS__)


weakly(self)的时候就变成了,如下:


metamacro_foreach_cxt1(rac_weakify_,, __weak,self)rac_weakify_(0,__weak ,self)


那么接下来就需要看 宏定义rac_weakify_的:

rac_weakify_:


#define rac_weakify_(INDEX, CONTEXT, VAR) \

CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR);


那么此时的rac_weakify_(0,__weak ,self)就应该写成:


__weak __typeof__(self) self_weak_ = self


weakly(self)弱化后的self 就这样实现了。

@strongify的定义:

先看strongify的定义:


#define strongify(...) \

rac_keywordify \

_Pragma("clang diagnostic push") \

_Pragma("clang diagnostic ignored \"-Wshadow\"") \

metamacro_foreach(rac_strongify_,, __VA_ARGS__) \

_Pragma("clang diagnostic pop")


去除没用的部分就剩下了:

metamacro_foreach(rac_strongify_,, __VA_ARGS__)部分,这部分的定义如下:


#define metamacro_foreach(MACRO, SEP, ...) \

metamacro_foreach_cxt(metamacro_foreach_iter, SEP, MACRO, __VA_ARGS__)


到了这里就是和之前的weakify部分一样的了。

就变成了metamacro_foreach_cxt(metamacro_foreach_iter,, rac_strongify_, __VA_ARGS__)

strongly(self)此时就变成了metamacro_foreach_cxt(metamacro_foreach_iter,, rac_strongify_, self)


#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \

metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)


接下来就是:


metamacro_foreach_cxt ## 1(metamacro_foreach_iter,, rac_strongify_, self)

metamacro_foreach_cxt1(metamacro_foreach_iter,, rac_strongify_, self)


接下来:


#define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)

======>

metamacro_foreach_cxt1(metamacro_foreach_iter,, rac_strongify_, self) === metamacro_foreach_iter(0, rac_strongify_, self)


接下来就是:metamacro_foreach_iter:


#define metamacro_foreach_iter(INDEX, MACRO, ARG) MACRO(INDEX, ARG)


那么此时的metamacro_foreach_iter(0, rac_strongify_, self) 就变成了:

metamacro_foreach_iter(0, rac_strongify_, self) = rac_strongify_(0, self)

再看rac_strongify_ ,那么就是:


#define rac_strongify_(INDEX, VAR) \

__strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_);


那么此时:

rac_strongify_(0, self)

=========>

__strong __typeof__(self) self = self_weak_

那么最后就变成了:


__weak __typeof__(self) self_weak_ = self

__strong __typeof__(self) self = self_weak_


需要注意的是:strong 必须在block中使用:


使用的方式如下:

__weak __typeof__ (self) self_weak_ = (self);

ViewController *VC = [[RootViewController alloc]init];

[VC successBlock:^{

__strong __typeof__(self) self = self_weak_;

}];

从上所述:

@weakify和@strongify 其实就是__weak 和 __strong 为了方式block中的循环引用而需要对本身对象的一个弱引用和强饮用。

@weakify === __weak

@strongify === __strong


你可能感兴趣的:(RAC的@weakify和@strongify)