-
block下循環引用的問題
- __block本身並不能避免循環引用,避免循環引用需要在block內部把__block修飾的obj置為nil
- __weak可以避免循環引用,但是其會導致外部對象釋放了之后,block 內部也訪問不到這個對象的問題,我們可以通過在 block 內部聲明一個 __strong
的變量來指向 weakObj,使外部對象既能在 block 內部保持住,又能避免循環引用的問題
-
__block與__weak功能上的區別。
- __block會持有該對象,即使超出了該對象的作用域,該對象還是會存在的,直到block對象從堆上銷毀;而__weak僅僅是將該對象賦值給weak對象,當該對象銷毀時,weak對象將指向nil;
- __block可以讓block修改局部變量,而__weak不能。
另外,MRC中__block是不會引起retain;但在ARC中__block則會引起retain。所以ARC中應該使用__weak。
因此,__block和__weak修飾符的區別其實是挺明顯的:
1.__block不管是ARC還是MRC模式下都可以使用,可以修飾對象,還可以修飾基本數據類型。
2.__weak只能在ARC模式下使用,也只能修飾對象(NSString),不能修飾基本數據類型(int)。
3.__block對象可以在block中被重新賦值,__weak不可以。
4.__block對象在ARC下可能會導致循環引用,非ARC下會避免循環引用,__weak只在ARC下使用,可以避免循環引用。
作者:知乎用戶
鏈接:https://www.zhihu.com/question/34593410/answer/59725212
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
鏈接:https://www.zhihu.com/question/34593410/answer/59725212
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
首先,block中為什么會用到weakself是因為要避免循環引用,一旦出現循環引用那么對象就會常駐內存。如果一個應用程序里面你有很多循環引用,那么內存占用就會比較大,這當然是誰都不想看到的結果。那么問題的重點就是:什么時候會出現循環引用?先來看一個例子:
NSArray *anArray = @[@"1", @"2", @"3"]; [anArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [self doSomething:idx]; }];
這種情況下,block中retain了self,當block中的代碼被執行完后,self就會被ARC釋放。所以不需要處理weakself的情況。
再來看一個例子:@interface aViewController () @property (nonatomic, strong) void(^aBlock)(id obj, NSUInteger idx, BOOL *stop); @end __weak aViewController *weakSelf = self; self.aBlock = ^(id obj, NSUInteger idx, BOOL *stop) { [weakSelf doSomething:idx]; }
這個例子的區別在於:block被self strong引用。所以結果就是block中引用了self,self引用了block。那么這個時候,如果你不使用weakself,則self和block永遠都不會被釋放。
那么是不是遇到block都要使用weakself呢?當然不是,而且如果全部使用weakself,會出現你想執行block中的代碼時,self已經被釋放掉了的情況。
另外,在處理weakself時,有兩種做法:__weak和__unsafe_unretained。兩種做法各有推薦,有的人覺得后者從字面上更好理解,而有的人覺得前者更加安全,因為self被釋放時會自動指向nil。有的人又說了,就是應該讓app崩潰才能發現問題所在。這個,看個人吧。