IOS开发资料库iOS异步多线程iOS 开发

block循环引用原理

2016-09-27  本文已影响248人  无边小猪

在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执行结束后。

上一篇下一篇

猜你喜欢

热点阅读