typedef int (^blk_t)(int); for(...){ blk_t blk = ^(int count) {return count;}; }雖然,這個block在循環內,但是blk的地址總是不變的。說明這個block在全局段。 【要點2】一種情況在非ARC下是無法編譯的: typedef int(^blk_t)(int); blk_t func(int rate){ return ^(int count){return rate*count;} } 這是因為:block捕獲了棧上的rate自動變量,此時rate已經變成了一個結構體,而block中擁有這個結構體的指針。即如果返回block的話就是返回局部變量的指針。而這一點恰是編譯器已經斷定了。在ARC下沒有這個問題,是因為ARC使用了autorelease了。 【要點3】有時候我們需要調用block 的copy函數,將block拷貝到堆上。看下面的代碼:
-(id) getBlockArray{ int val =10; return [[NSArray alloc]initWithObjects: ^{NSLog(@"blk0:%d",val);}, ^{NSLog(@"blk1:%d",val);},nil]; } id obj = getBlockArray(); typedef void (^blk_t)(void); blk_t blk = (blk_t){obj objectAtIndex:0}; blk();這段代碼在最後一行blk()會異常,因為數組中的block是棧上的。因為val是棧上的。解決辦法就是調用copy方法。 【要點4】不管block配置在何處,用copy方法復制都不會引起任何問題。在ARC環境下,如果不確定是否要copy block盡管copy即可。ARC會打掃戰場。 注意:在棧上調用copy那麼復制到堆上,在全局block調用copy什麼也不做,在堆上調用block 引用計數增加
typedef int (^blkt1)(void) ; -(void) stackOrHeap{ __block int val =10; int *valPtr = &val;//使用int的指針,來檢測block到底在棧上,還是堆上 blkt1 s= ^{ NSLog(@"val_block = %d",++val); return val;}; s(); NSLog(@"valPointer = %d",*valPtr); }在ARC下>>>>>>>>>>>該block被會直接生成到堆上了。看log: val_block = 11 valPointer = 10 在非ARC下>>>>>>>>>該block還是在棧上的。 看log:val_block = 11 valPointer = 11
調用copy之後的結果呢:
-(void) stackOrHeap{ __block int val =10; int *valPtr = &val;//使用int的指針,來檢測block到底在棧上,還是堆上 blkt1 s= ^{ NSLog(@"val_block = %d",++val); return val;}; blkt1 h = [s copy]; h(); NSLog(@"valPointer = %d",*valPtr); }
----------------在ARC下>>>>>>>>>>>無效果。 val_block = 11 valPointer = 10
----------------在非ARC下>>>>>>>>>確實復制到堆上了。 val_block = 11 valPointer = 10