ReactiveCocoa 之 @weakify/@strongify

@weakify 和 @strongify 是 RAC 中對于強(qiáng)弱引用操作的宏定義。

1. 拆解宏定義

下面的代碼以 self 作為例子,也就是說,括號中也可以是其他對象。

// @weakify(self) 實(shí)際上被宏定義為:
#define weakify(...) \
    ext_keywordify \
    metamacro_foreach_cxt(ext_weakify_,, __weak, __VA_ARGS__)
// 經(jīng)過拆解,最終實(shí)際上是這樣:
autoreleasepool {}__weak __typeof__(self) self_weak_ = self

@weakify 相當(dāng)于定義了一個(gè) _weak 弱引用,self 類型的指針變量 self_weak,指向 self 的值。

// @strongify(self)實(shí)際上被宏定義為:
#define strongify(...) \
    ext_keywordify \
    _Pragma("clang diagnostic push") \
    _Pragma("clang diagnostic ignored \"-Wshadow\"") \
    metamacro_foreach(ext_strongify_,, __VA_ARGS__) \
    _Pragma("clang diagnostic pop")
// 經(jīng)過拆解,最終實(shí)際上是這樣:
autoreleasepool {}__typeof__(self) self = self_weak_;

而 @strongify 相當(dāng)于定義了一個(gè)名為 self 的變量,指向 self_weak_ 所指向的值。同時(shí),抑制了同名錯(cuò)誤,作用會(huì)在下文詳解。

2. 內(nèi)存管理

考慮如下例子:

void useWeakifyStrongify() {
    @weakify(self);
    self.someBlock = ^ { 
        @strongify(self); 
        NSLog(@"%@", self);
    }
}

2.1 代碼執(zhí)行前

在對象創(chuàng)建之時(shí),self 指針就強(qiáng)引用了 self obj 對象。

執(zhí)行前

2.2 代碼執(zhí)行 @weakify(self):

結(jié)合上文拆解的宏定義,@weakify 操作定義了一個(gè)名為 self_weak_ 的變量,弱引用 self obj。

執(zhí)行@weakify

2.3 代碼執(zhí)行 @strongify(self):

@strongify 做了如下操作:在 block 的作用域里,創(chuàng)建了一個(gè)局部變量,名稱為 self,覆蓋了外部的 self 變量。由于在宏定義中抑制了 "warn whenever a local variable shadows another local variable." 錯(cuò)誤,所以編譯器不會(huì)報(bào)重名錯(cuò)誤。這樣做的好處是我們?nèi)匀豢梢栽?block 中使用 self 作為變量名,不需要額外定義變量。

其實(shí) block 可以表示成直接引用 self obj,這里為了表明邏輯關(guān)系,先經(jīng)過了 self(local) ,然后間接的指向了 self obj。

執(zhí)行@strongify

2.4 嵌套情況

對于嵌套使用 block 的情況,則需要多次插入 @strongify 來避免循環(huán)引用:

void nestedBlocksStrongify() {
    @weakify(self);
    self.someBlock = ^ {  // outside block
        @strongify(self);
        self.anotherBlock = ^{  // inside block
            @strongify(self);
            NSLog(@"%@", self);
        };
    };
}

3. 總結(jié)

可以看到,RAC 的設(shè)計(jì)者通過使用 @strongify 和 @weakify 后,達(dá)到了以下三點(diǎn):

  • 避免循環(huán)引用。上圖中不存在環(huán)。
  • 避免當(dāng)弱指針指向 self obj 時(shí),self obj 被其他操作釋放后,成為野指針的問題。因?yàn)樵?local 作用域中始終有個(gè)強(qiáng)指針指向 self obj。
  • 避免新建變量名。傳統(tǒng)的 __weak 方法解決循環(huán)引用時(shí),需要定義新的變量來保存 self obj 的若指針。但是使用 @strongify 后,在 local 作用域中定義了一個(gè)同名的 self 變量,所以不需要額外定義新的變量,直接用 self 就可以使用 self。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容