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