當(dāng) Block 直接或間接的被當(dāng)前對象持有時卿嘲,如果 Block 也強引用當(dāng)前對象颂斜,就會造成循環(huán)引用。
解決方案一:讓 Block 捕獲弱引用的 self拾枣。
__weak typeof(self) weakSelf = self;
self.myBlock = ^(NSUInteger index) {
[weakSelf doSomething:index];
}
解決方案二:把 self 當(dāng)參數(shù)傳進去沃疮。
@property (nonatomic, copy) void(^myBlock)(__kindof AGStudentModel *selfRef);
AGStudentModel *sm = [AGStudentModel new];
sm.myBlock = ^(AGStudentModel *sm) {
[sm doSomething];
};
sm.myBlock(sm);
解決方案三:在 Block 使用完后把對象持有 Block屬性制空。
《Effective Objective-C 2.0》講到的從內(nèi)部打破循環(huán)引用梅肤。
AGStudentModel *sm = [AGStudentModel new];
sm.myBlock = ^(int index) {
sm.name = @"kobe";
// 制空 block
sm.myBlock = nil;
};
sm.myBlock(24);
或---者
AGStudentModel *sm = [AGStudentModel new];
__block AGStudentModel *blockSelf = sm;
sm.myBlock = ^(int index) {
blockSelf.name = @"kobe";
// 制空 blockSelf
blockSelf = nil;
};
sm.myBlock(24);
個人看法:
第一種方案:
用的比較多司蔬,缺點是用的時候代碼多,其實 Block 內(nèi)部使用 self 時還是要強引用回來姨蝴,這樣比較安全俊啼。而且代碼看起來比較亂。
第二種方案:
比較直接左医,就是設(shè)計 Block 時要寫多一個參數(shù)授帕。不管是調(diào)用方還是設(shè)計方,使用起來都很方便炒辉,代碼干凈豪墅。不過對于間接的循環(huán)引用問題比較棘手泉手,設(shè)成接收 id 類型黔寇,然后還要類型轉(zhuǎn)換。
第三種方案:
比較有思想斩萌,幫循環(huán)引用問題解決在了內(nèi)部缝裤∑梁洌可是調(diào)用方不能直觀地知道你是這樣設(shè)計的。其次就是我用屬性保存是持有的性質(zhì)憋飞,怎么用完一次就釋放霎苗?多次調(diào)用還會引起奔潰或self值為nil,感覺不太理想榛做⊙湔担可能特殊情況會比較適合,例如網(wǎng)絡(luò)模塊設(shè)計检眯。
我個人比較偏向第二種厘擂。
- 理由一,不用寫過多代碼锰瘸。
- 理由二刽严,代碼寫起來一塊一塊的,這才是代碼塊嘛避凝。
- 理由三舞萄,調(diào)用方一看就知道干啥,方便又安全管削。