當self強引用了block時,再在block中調用self會引發(fā)循環(huán)引用問題。所以拨黔,為了避免這種情況好乐,都會使用weak-strong來解除循環(huán)引用問題匾竿。
如下所示
__weak typeof(self) weak_self = self;
a_block = ^{
__strong typeof(weak_self) strong_self = weak_self;
strong_self.view = ...
};
代碼解釋
weak變量weak_self
與self
指向相同地址
在block中調用weak_self
則不會導致循環(huán)引用。因為weak_self
是weak修飾蔚万,所以不會增加self
的引用計數(shù)岭妖。只有self
對block
的單向引用。
將weak變量轉為strong變量則是為了在block執(zhí)行期間不會被釋放反璃。因為weak變量不會影響對象的引用計數(shù)昵慌,對象可以正常釋放,當對象釋放之后該指針就變?yōu)閚il淮蜈。而將weak變量轉為strong變量斋攀,則strong變量會持有該對象,所以在block執(zhí)行期間梧田,這個對象不會被釋放淳蔼,當block執(zhí)行完畢之后,strong變量被銷毀裁眯,該對象的持有減少肖方。正常釋放。
問題
這樣的寫法需要在所有block的地方添加這兩行代碼
__weak typeof(self) weak_self = self;
__strong typeof(weak_self) strong_self = weak_self;
優(yōu)雅的寫法
定義一個宏定義
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif
#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif
當使用的時候
@weakify(self)
blcok = ^{
@strongify(self)
self.view = ...
}
代碼解釋
首先看這個宏定義
這個宏定義關鍵的是在于這個
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
autoreleasepool{}
這個是沒有實質作用的未状,只是為了當使用這個宏的時候再宏開頭可以添加一個@
符號俯画,讓使用方式更像其他語言的語法糖一樣。
然后是__weak __typeof__(object) weak##_##object = object
, 后面部分中##
是用于連接的
weak##_
解析之后就是 weak_
,然后再與##object
連接司草,所以最終就是weak_object
,object是宏中傳遞進來的參數(shù)艰垂。
所以當使用這個宏的時候
@weakify(self)
其實就轉換成了
__weak __typeof__(self) weak_self = self;
所以調用的時候應該是調用weak_self
然后來看這個宏
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
這個宏的不同的地方是在__typeof__(object) object = weak##_##object
當我們傳入self
的時候這里就變成了這樣
__typeof__(self) self = weak_self
即定義一個self
變量來指向和weak_self
相同的地址
所以在下面使用的self
其實是自己定義的這個變量self
所以 這個兩個宏聯(lián)合起來使用的過程簡化來說
- 將
self
指針賦值給weak
類型的weak_self
變量 - 再將
weak_self
賦值給strong
類型的自己定義self
變量泡仗,只不過這個變量和系統(tǒng)的self
指針同名。所以在使用時雖然仍然使用的是self猜憎,但已經替換為自己定義的self