我看過不少文章關於在dispatch_async的block裏面使用_weak self, 可是讓我疑惑的是,如下代碼是否須要必須使用_weak self, 由於我也看到了不少觀點說,在有些狀況下不須要使用__weak self.objective-c
self.myQueue = dispatch_queue_create("com.biview.core_data", NULL);
dispatch_async(self.myQueue, ^(void){
if(!self.var1){
self.var1 =
}
dispatch_async(dispatch_get_main_queue(), ^(void){
if([self.var2 superview]) {
[self.var2 removeFromSuperview];
}
[self.Label setText:text];
});
});複製代碼
針對上面的問題,咱們假設:self是指向UIViewController的對象指針。
考慮如下幾點:iview
在上面的例子中,self是在主線程的隊列中,沒必要擔憂有任何bug產生。異步
當在dispatch的異步隊列的block中捕獲到self時,self會被執行retained操做,當block執行完畢後self執行released操做。
這意味着:當block執行完畢後,self的生命週期纔會結束。上例中的第二個block是在主線程的隊列中,它保證了self一直存活着當這個block被執行的時候。
在程序中存在潛在危險的操做是:延長 self 的生命週期。async
若是你明確的不但願延長UIViewController對象的生命週期,而是當block被執行的時候去檢查UIViewController對象究竟是否存在,你可使用 _weak self. 須要注意的是block最後都會被執行,無論UIViewController是否存活仍是已經被釋放了。fetch
若是你但願若是UIViewController已經被釋放了,那麼block不作任何事情,能夠寫成 _weak self.atom
MyController * _weak weakSelf = self;
dispatch_async(queue, ^{
MyController *strongSelf = weakSelf;
if(strongSelf){
...
}else {
// self has been deallocted in the meantime.
}
});複製代碼
不能在非主線程中向UIKit對象發送消息。
另外一個細微的錯誤可能發生在UIKit對象執行方法在非主線程。spa
若是block在異步線程中捕獲了一個UIKit對象,可能發生的是:block 是最後一個持有改UIKit的強引用。當block執行完的時候,UIKit對象將被release,由於是UIKit對象的最後一個強引用,全部該UIKit對象將被釋放,可是,釋放操做發生在block所執行的線程-它不是主線程,全部,風險即將發生,UIKit對象的dealloc方法將被調用(UI 對象應該在主線程中被回收,由於在它們的 dealloc 方法被調用回收的時候,可能會去改變 view 的結構關係,而如咱們所知,這種操做應該放在主線程來進行,見參考二)。線程
避免這個錯誤:指針
UIViewController *strongUIKitPointer = ...
dispatch_async(non_main_queue), ^{
...//do someting
dispatch(dispatch_get_main_queue(),^{
[strongUIkitPointer self]; //self is a method, too -doing nothing.
});
});複製代碼
雙向強引用發生在:一個強類型對象A持有一個強類型對象B,而且對象B強引用對象A。「Block」是一個強引用對象。code
人爲的雙向強引用舉例:
typedef void(^my_completion_block_t)(NSArray* result);
@interface UserViewController : UIViewController
@property (nonatomic, copy) my_completion_block_t completion;
@property (nonatomic) NSArray *users;複製代碼
on "UserViewController.m"
self.completion = ^(NSArray *users){
self.users = users;
}
[self fetchUsers];複製代碼
這是一個典型了強引用循環。UserViewController 有一個Block類型的屬性,全部UserViewController對象強引用着block。而block捕獲到self的時候執行強引用操做,全部造成了強引用循環。
解決方式:
使用_weak 指針指向self.
UserViewController * _weak weakSelf = self;
self.completion = ^(NSArray *user){
UsersViewController *strongSelf = weakSelf;
if(strongSelf){
strongSelf.users = users;
}else{
// the view controller does not exist anymore.
}
};複製代碼
使用block 指針執行self, 執行完畢後將block 指針指向nil.
UsersViewController *__block blockSelf = self;
self.completion=^(NSArayy *users){
self.completion = ^(NSArray *users){
blockSelf.users = users;
blockSelf = nil;
}
}複製代碼
--完--