block循环引用问题

        从iOS4.0开始,objective C中引入了block技术。block跟标准c的函数类似,block的引入使得代码回调更加方便。

优点:

(1)、回调直接写在需要触发的地方,使代码更具有连续性。

(2)、在代码块内部可以访问局部变量


但是,如果block使用不慎,将引起内存泄露。


1、为啥会引起内存泄露?

在block代码块里,如果传入了代码块外部的对象,block会对该对象进行retain,持有该对象,造成循环引用。

eg:

@interface TestBlockObject : NSObject

- (void)invokeBlock:(void (^)(void))testBlock;

@end


@implementation TestBlockObject


- (void)invokeBlock:(void (^)(void))testBlock{

    NSLog(@"TestBlockObject");

}

@end


//调用

@interface ViewController ()

{

    TestBlockObject *ob;

}

@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    ob = [TestBlockObject new];

    [ob invokeBlock:^{

        //引起循环引用

        [self testPrint];

    }];

}


- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


- (void)testPrint{

    NSLog(@"哈哈");

}

@end


引起循环引用的地方


[ob invokeBlock:^{

        //引起循环引用

        [self testPrint];

    }];


ViewController(self)持有ob,ob的block中持有self,导致了循环引用。self对象将不会被销毁,从而ob也不会被销毁,引起内存泄露。


2、解决循环引用方法

使用以下的代码替换红色代码


__weak typeof(self) weakSelf = self;

    [ob invokeBlock:^{

        

        if (weakSelf) {

            [weakSelf testPrint];

        }

        

    }];

通过将self转换成weak对象,然后再block中使用,破坏循环引用。


3、特殊的地方

若在ViewController的viewDidLoad加入下方的代码,是不会导致循环引用的。因为代码块是类方法,ViewController没有持有该部分内存。当block执行结束后,block就会被释放掉,因而self就不会被持有。

[UIView animateWithDuration:0.5 animations:^{

        [self testPrint];

    }];


你可能感兴趣的:(循环引用,block,内存控制)