RAC的@weakify和@strongify

在使用RAC的代碼中看到@weakify和@strongify的使用疾党,第一感覺(jué)應(yīng)該是 __weak和__strong的使用,于是就看了一下口叙,關(guān)于這兩者的定義:

@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.

創(chuàng)建一個(gè)weak的變量引用作為參數(shù)提供給每一個(gè)需要調(diào)用的地方担孔,之后能夠再一次變成strong 通過(guò)strongify的方式替蛉。

那接下來(lái)就看一下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__)這部分是參數(shù),我們之后再來(lái)看冠胯,先看metamacro_concat 這個(gè)的定義:

metamacro_concat:


#define metamacro_concat(A, B) \

metamacro_concat_(A, B)


接下來(lái)是metamacro_concat_ 這個(gè)函數(shù)的定義:

metamacro_concat_:


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


這個(gè)函數(shù)首先要認(rèn)清運(yùn)算符 “##” 火诸,這里是連字符的意思,就是A ## B == AB


那么倒推到上面的的宏定義就變成:


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

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


接下來(lái)就需要先看這個(gè)metamacro_argcount:荠察,之后后面需要連接的參數(shù)是什么置蜀。

metamacro_argcount:返回參數(shù)的個(gè)數(shù)


* 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)


通過(guò)函數(shù)的注釋可以看出:這個(gè)函數(shù)返回的是參數(shù)的個(gè)數(shù)奈搜,為了驗(yàn)證那么需要繼續(xù)看定義這個(gè)宏的其它的宏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__)


通過(guò)宏的注釋可以得到:返回N個(gè)可辨的參數(shù),至少需要給出N+1 個(gè)可變的參數(shù)盯荤,而且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)的樣子。

然后看函數(shù)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__)


這時(shí)需要看metamacro_head 的定義:


#define metamacro_head(...) \

metamacro_head_(__VA_ARGS__, 0)


根據(jù)定義的注釋:* Returns the first argument given. At least one argument must be provided.

可以得知廷雅,返回第一個(gè)參數(shù)耗美,而且至少需要一個(gè)參數(shù)。

進(jìn)一步去看宏定義metamacro_head_航缀,


#define metamacro_head_(FIRST, ...) FIRST


那么就可以知道此時(shí)的metamacro_head返回的是參數(shù)列表的第一個(gè)參數(shù)商架。

那么之前的宏的定義:

metamacro_at20( __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)返回的是參數(shù)列表中參數(shù)的個(gè)數(shù),就是__VA_ARGS__參數(shù)的個(gè)數(shù)芥玉。

也就是metamacro_at20 返回的是N蛇摸,而N是__VA_ARGS__的個(gè)數(shù)。

于是最上面的: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__)


假如此時(shí)傳入的是self的話那么此時(shí)就會(huì)變成:

metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, __VA_ARGS__)這樣赶袄,也就是weakify(...) 轉(zhuǎn)換后的形式。

那就看一下metamacro_foreach_cxt1 的宏定義:


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


而我們?cè)诙xweakify的時(shí)候傳遞的參數(shù)是:

#define weakify(...) \

rac_keywordify \

metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)

所以我們的參數(shù)是:rac_weakify_,, __weak, __VA_ARGS__


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


weakly(self)的時(shí)候就變成了抠藕,如下:


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


那么接下來(lái)就需要看 宏定義rac_weakify_的:

rac_weakify_:


#define rac_weakify_(INDEX, CONTEXT, VAR) \

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


那么此時(shí)的rac_weakify_(0,__weak ,self)就應(yīng)該寫成:


__weak __typeof__(self) self_weak_ = self


weakly(self)弱化后的self 就這樣實(shí)現(xiàn)了饿肺。

@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")


去除沒(méi)用的部分就剩下了:

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)此時(shí)就變成了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__)


接下來(lái)就是:


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

metamacro_foreach_cxt1(metamacro_foreach_iter,, rac_strongify_, self)


接下來(lái):


#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)


接下來(lái)就是:metamacro_foreach_iter:


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


那么此時(shí)的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_);


那么此時(shí):

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 其實(shí)就是__weak 和 __strong 為了方式block中的循環(huán)引用而需要對(duì)本身對(duì)象的一個(gè)弱引用和強(qiáng)飲用溉跃。

@weakify === __weak

@strongify === __strong


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市告抄,隨后出現(xiàn)的幾起案子撰茎,更是在濱河造成了極大的恐慌,老刑警劉巖打洼,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄糊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡拟蜻,警方通過(guò)查閱死者的電腦和手機(jī)绎签,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)酝锅,“玉大人诡必,你說(shuō)我怎么就攤上這事。” “怎么了爸舒?”我有些...
    開(kāi)封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵蟋字,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我扭勉,道長(zhǎng)鹊奖,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任涂炎,我火速辦了婚禮忠聚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘唱捣。我一直安慰自己两蟀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布震缭。 她就那樣靜靜地躺著赂毯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拣宰。 梳的紋絲不亂的頭發(fā)上党涕,一...
    開(kāi)封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音巡社,去河邊找鬼膛堤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛晌该,可吹牛的內(nèi)容都是我干的骑祟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼气笙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了怯晕?” 一聲冷哼從身側(cè)響起潜圃,我...
    開(kāi)封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎舟茶,沒(méi)想到半個(gè)月后谭期,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吧凉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年隧出,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阀捅。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胀瞪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凄诞,我是刑警寧澤圆雁,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站帆谍,受9級(jí)特大地震影響伪朽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜汛蝙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一烈涮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窖剑,春花似錦坚洽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至翠储,卻和暖如春绘雁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背援所。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工庐舟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人住拭。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓挪略,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親滔岳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杠娱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容