__block變量存儲域
|
影響
|
棧
|
從棧複製到堆並被Block持有
|
堆
|
被Block持有
|
typedef
void (^aBlock)(
id);
aBlock ablock; { id array=[[NSMutableArrayalloc]init]; ablock=^(id objct){ [array addObject:objct]; NSLog(@"array count %d",[arraycount]); }; } ablock([[NSObjectalloc]init]); ablock([[NSObjectalloc]init]);
|
- 調用Block的copy實例方法
- Block作爲函數返回值
- 將Block賦值給附有__strong修飾符id類型的類或Block類型成員變量時
- 在方法名含有usingBlock的Cocoa框架方法或Grand Central Dispatch的API中傳遞Block時。
- Block作爲函數值返回時
- 將Block賦值給附有__strong修飾符id類型的類或Block類型成員變量時
- 在方法名含有usingBlock的Cocoa框架方法或Grand Central Dispatch的API中傳遞Block時。
Person.m文件代碼
主程序代碼:
{
...
Person *per=[[Personalloc]init];
NSLog(@"o");
...
}
|
-(id)init{
self=[superinit]; id __weak tmp=self; blk_=^{ NSLog(@"self %@",tmp); }; return self; }
|
//arc打開狀態
@interface Person(){ void(^blk_)(void); id obj; } @end @implementation Person -(void)dealloc{ NSLog(@"person dealloc"); } -(id)init{ self=[superinit]; blk_=^{ NSLog(@"obj %@",obj); }; return self; }
|
//arc打開狀態
@interface Person(){ void(^blk_)(void); } @end @implementation Person -(void)dealloc{ NSLog(@"person dealloc"); } -(id)init{ self=[superinit]; __block id tmp=self; blk_=^{ NSLog(@"obj %@",tmp); tmp=nil; } ; return self; } -(void)execBlock{ blk_(); } |
該代碼沒有引起循環引用,但是如果不調用execBlock這個方法,即不執行對tmp的賦值,就會引起循環引用。
通過執行execBlock,__block變量tmp對Person類對象的強引用失效。
|
- 通過__block變量可控制對象的持有時間
- 在不能使用__weak修飾符的環境下代替__unsafe_unretained修飾符,不必擔心懸垂指針。
ARC無效時,需要手動將Block從棧複製到堆,用copy方法來複制,release方法來釋放。只要Block位於堆上,則可以通過retain方法持有,對於棧上的Block調用retain方法不起任何作用。在c語言中也可以使Block,此時使用Block_copy和Block_release代替copy/release實例方法。另外,ARC無效時,__block說明符被用來避免Block循環引用,這是因爲Block從棧複製到堆時,若Block使用的變量爲附有__block說明符的id類型對象或對象類型自動變量,不會被retain,反之如果沒有__block說明符則會被retain。
Block部分到此結束。