在block中調用self就回造成循環引用?當然不是。要創造出一個循環引用的block需要兩個條件:
1、在block中引用了self
2、對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);
}
打印結果:
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所在類時dealloc并未被調用
若代碼略做修改
@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);
}
打印結果:
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所在類時dealloc被調用
從上述兩段代碼可以看出,若僅在block中調用self是并不足以導致循環引用的,而真正導致循環引用的是copy的執行,copy執行后self引用計數器加1,self被block強引用,造成循環引用問題。
而解決該問題的方式是在MRC下定義:
__block typeof(self) weakself =self;
在ARC下定義:
__weak typeof(self) weakself =self;
在block循環引用的解決辦法中weak-strong dance是比較特別的一個,該方法可以通過在執行block過程中持有self,block執行結束后釋放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));
打印結果如下:
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
上述打印結果中可以看出在hellfun()執行過程中短暫的強引用了self,而當hellofun()執行結束后,局部變量strongSelf被釋放,引用計數減1,不再強引用self。
此種方法可避免在block執行的過程中self被釋放而引發的異常。如果block執行過程中self的釋放將被推遲到block執行結束后。