iOS中Block的循環引用問題

iOS中Block的循環引用問題

每週總結,第一週開始啦,最近在看AFNetworking源碼時,看到了__strong的使用,很慚愧的說在平時開發中從來沒有使用過__strong self ,除此之外,發現自己對Block的循環引用理解的也不深刻,今天就總結下block的循環引用問題

AFNetworking中__strongSelf應用如下


AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;
        strongSelf.networkReachabilityStatus = status;
        if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
        }
    };

本文將從以下幾個方面介紹ARC下block的循環引用問題:
1. 什麼是循環引用
2. 循環引用的結果
3. ARC下Block怎樣產生的循環引用
4. 怎麼樣解決循環引用

1、什麼是循環引用?
兩個對象相互持有,導致兩個對象都不能釋放,造成內存泄漏。

2、如何產生了循環引用
觀察以下代碼存在些什麼問題

@interface ViewController ()
@property (nonatomic, copy) void(^ testBlock)();
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.testBlock = ^(void){
        [self doSomeThing];
    };
}
-(void)doSomeThing{
    NSLog(@"you are doing something");
}
@end

在上述代碼中,XCode編譯後提示[self doSomeThing],這一行可能會導致循環引用。
因爲無論testBlock是copy還是strong屬性,self都強引用了testBlock,在testBlock內部又調用了self,此時,testBlock強引用self(self的引用計數+1),導致ViewController實例無法被釋放,因爲自身的變量的引用計數永遠大於1,循環引用。

爲了解決這種問題,可以聲明一個__weak變量指向self,在blcok中使用這個__weak變量,就不會導致self的引用計數+1,不會出現循環引用的問題了。

@interface ViewController ()
@property (nonatomic, copy) void(^ testBlock)();
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    __weak __typeof(self)weakSelf = self;

    self.testBlock = ^(void){
        [weakSelf doSomeThing];
    };
}

-(void)doSomeThing{
    NSLog(@"you are doing something");
}

@end

循環引用問題解決了,但是這時還有其他的問題,當你加了weakSelf後,Block中的self隨時都會有被釋放的可能,所以會出現一種情況,在異步調用的時候,執行到Block代碼塊時,self可能已經釋放爲nil了,所以爲了避免這種情況發生,我們會重新strong self。一般情況下,我們都應該這麼做,畢竟這麼做是沒什麼風險,除非你不關心self在執行過程中變成nil,或者你確定它不會變成nil。

__weak __typeof(self)weakSelf = self;
self.testBlock = ^{
    __strong __typeof(weakSelf)strongSelf = weakSelf;
    [strongSelf doSomeThing];
}];

weakSelf是爲了block弱引用self,避免循環引用,而再聲明一個strongSelf是因爲一旦進入block執行,就不允許self在這個執行過程中釋放。block執行完後這個strongSelf會自動釋放,沒有循環引用問題。

到此,有關本人對weakSelf的使用歷程就介紹完畢啦,後續學習到新的知識,再更新,收車。

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