當(dāng) Block 直接或間接的被當(dāng)前對象持有時(shí),如果 Block 也強(qiáng)引用當(dāng)前對象,就會造成循環(huán)引用。
解決方案一:讓 Block 捕獲弱引用的 self。
__weak typeof(self) weakSelf = self;
self.myBlock = ^(NSUInteger index) {
[weakSelf doSomething:index];
}
解決方案二:把 self 當(dāng)參數(shù)傳進(jìn)去。
@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);
個(gè)人看法:
第一種方案:
用的比較多,缺點(diǎn)是用的時(shí)候代碼多,其實(shí) Block 內(nèi)部使用 self 時(shí)還是要強(qiáng)引用回來,這樣比較安全。而且代碼看起來比較亂。
第二種方案:
比較直接,就是設(shè)計(jì) Block 時(shí)要寫多一個(gè)參數(shù)。不管是調(diào)用方還是設(shè)計(jì)方,使用起來都很方便,代碼干凈。不過對于間接的循環(huán)引用問題比較棘手,設(shè)成接收 id 類型,然后還要類型轉(zhuǎn)換。
第三種方案:
比較有思想,幫循環(huán)引用問題解決在了內(nèi)部??墒钦{(diào)用方不能直觀地知道你是這樣設(shè)計(jì)的。其次就是我用屬性保存是持有的性質(zhì),怎么用完一次就釋放?多次調(diào)用還會引起奔潰或self值為nil,感覺不太理想??赡芴厥馇闆r會比較適合,例如網(wǎng)絡(luò)模塊設(shè)計(jì)。
我個(gè)人比較偏向第二種。
- 理由一,不用寫過多代碼。
- 理由二,代碼寫起來一塊一塊的,這才是代碼塊嘛。
- 理由三,調(diào)用方一看就知道干啥,方便又安全。