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];

    }];


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章