在block中調(diào)用self就回造成循環(huán)引用蝇狼?當(dāng)然不是珍语。要?jiǎng)?chuàng)造出一個(gè)循環(huán)引用的block需要兩個(gè)條件:
1片林、在block中引用了self
2茁计、對(duì)block做了copy操作
例如:
@interface testClass : NSObject
@property(nonatomic,copy) Fun fun;
@end
......
-(void)testBlock
{
testClass *tctemp = [[testClass alloc] init];
self.tc = tctemp;
[tctemp release];
NSLog(@"a count %d",self.retainCount);
void (^function)()=^(){
self.name = @"hello";
};
function();
NSLog(@"a count %d",self.retainCount);
}
打印結(jié)果:
2016-09-27 10:03:58.131 test[4085:29450] a count 4
2016-09-27 10:03:58.132 test[4085:29450] a count 4
釋放self所在類時(shí)dealloc并未被調(diào)用
若代碼略做修改
@interface testClass : NSObject
@property(nonatomic,copy) Fun fun;
@end
......
-(void)testBlock
{
testClass *tctemp = [[testClass alloc] init];
self.tc = tctemp;
[tctemp release];
NSLog(@"a count %d",self.retainCount);
void (^function)()=^(){
self.name = @"hello";
};
self.tc.fun = function;
self.tc.fun();
NSLog(@"a count %d",self.retainCount);
}
打印結(jié)果:
2016-09-27 10:06:32.456 test[4350:31404] a count 4
2016-09-27 10:06:32.459 test[4350:31404] a count 5
釋放self所在類時(shí)dealloc被調(diào)用
從上述兩段代碼可以看出,若僅在block中調(diào)用self是并不足以導(dǎo)致循環(huán)引用的启绰,而真正導(dǎo)致循環(huán)引用的是copy的執(zhí)行昂儒,copy執(zhí)行后self引用計(jì)數(shù)器加1,self被block強(qiáng)引用委可,造成循環(huán)引用問題渊跋。
而解決該問題的方式是在MRC下定義:
__block typeof(self) weakself =self;
在ARC下定義:
__weak typeof(self) weakself =self;
在block循環(huán)引用的解決辦法中weak-strong dance是比較特別的一個(gè),該方法可以通過在執(zhí)行block過程中持有self着倾,block執(zhí)行結(jié)束后釋放block來解決一些問題拾酝。
用法如下:
NSLog(@"self:%ld", CFGetRetainCount((__bridge CFTypeRef)self));
__weak typeof(self) weakSelf = self;
NSLog(@"self:%ld", CFGetRetainCount((__bridge CFTypeRef)self)); void (^hellofun)()= ^{
typeof(weakSelf) strongSelf = weakSelf;
strongSelf;
NSLog(@"self:%ld", CFGetRetainCount((__bridge CFTypeRef)strongSelf));
};
hellofun();
NSLog(@"self:%ld", CFGetRetainCount((__bridge CFTypeRef)self));
打印結(jié)果如下:
2016-09-27 11:37:32.900 arctest[1128:943736] self:3
2016-09-27 11:37:32.900 arctest[1128:943736] self:3
2016-09-27 11:37:32.900 arctest[1128:943736] self:4
2016-09-27 11:37:32.900 arctest[1128:943736] self:3
上述打印結(jié)果中可以看出在hellfun()執(zhí)行過程中短暫的強(qiáng)引用了self,而當(dāng)hellofun()執(zhí)行結(jié)束后卡者,局部變量strongSelf被釋放蒿囤,引用計(jì)數(shù)減1,不再強(qiáng)引用self崇决。
此種方法可避免在block執(zhí)行的過程中self被釋放而引發(fā)的異常材诽。如果block執(zhí)行過程中self的釋放將被推遲到block執(zhí)行結(jié)束后底挫。