这是一篇比较长的博文,前部分是block的测试题目,中间是block的语法、特性,block讲解block内部实现和block存储位置,请读者耐心阅读。具备block基础的同学,直接调转到block的实现
下面列出了五道题,看看能否答对两三个。主要涉及block栈上、还是堆上、怎么捕获变量。答案在博文最后一行
//-----------第一道题:-------------- void exampleA() { char a = 'A'; ^{ printf("%c\n", a);}; } A.始终能够正常运行 B.只有在使用ARC的情况下才能正常运行 C.不使用ARC才能正常运行 D.永远无法正常运行 //-----------第二道题:答案同第一题-------------- void exampleB_addBlockToArray(NSMutableArray *array) { char b = 'B'; [array addObject:^{printf("%c\n", b);}]; } void exampleB() { NSMutableArray *array = [NSMutableArray array]; exampleB_addBlockToArray(array); void (^block)() = [array objectAtIndex:0]; block(); } //-----------第三道题:答案同第一题-------------- void exampleC_addBlockToArray(NSMutableArray *array) { [array addObject:^{printf("C\n");}]; } void exampleC() { NSMutableArray *array = [NSMutableArray array]; exampleC_addBlockToArray(array); void (^block)() = [array objectAtIndex:0]; block(); } //-----------第四道题:答案同第一题-------------- typedef void (^dBlock)(); dBlock exampleD_getBlock() { char d = 'D'; return ^{printf("%c\n", d);}; } void exampleD() { exampleD_getBlock()(); } //-----------第五道题:答案同第一题-------------- typedef void (^eBlock)(); eBlock exampleE_getBlock() { char e = 'E'; void (^block)() = ^{printf("%c\n", e);}; return block; } void exampleE() { eBlock block = exampleE_getBlock(); block(); }
注:以上题目摘自:CocoaChina论坛点击打开链接
int main(){ void (^blk)(void) = ^{printf("block\n");}; blk(); return 0; }
struct __block_impl{ void *isa; int Flags; int Reserved; void *FuncPtr; }; static struct __main_block_desc_0{ unsigned long reserved; unsigned long Block_size }__main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)}; struct __main_block_impl_0{ struct __block_impl impl; struct __main_block_desc_0 *Desc; } static struct __main_block_func_0(struct __main_block_impl_0 *__cself) { printf("block\n"); } int main(){ struct __main_block_impl_0 *blk = &__main_block_impl_0(__main_block_func_0,&__main_block_desc_0_DATA); (*blk->impl.FuncPtr)(blk); }
__main_block_impl_0{ void *isa; int Flags; int Reserved; void *FuncPtr; struct __main_block_desc_0 *Desc; }
int val = 10; void (^blk)(void) = ^{printf("val=%d\n",val);}; val = 2; blk();
上面这段代码,输出值是:val = 10.而不是2.block截获自动变量的瞬时值。因为block保存了自动变量的值,所以在执行block语法后,即使改写block中使用的自动变量的值也不会影响block执行时自动变量的值。
__main_block_impl_0{ void *isa; int Flags; int Reserved; void *FuncPtr; struct __main_block_desc_0 *Desc; int val; }
int main(){ struct __main_block_impl_0 *blk = &__main_block_impl_0(__main_block_func_0,&__main_block_desc_0_DATA,val); }注意函数调用最后一个参数,即val参数。
static struct __main_block_func_0(struct __main_block_impl_0 *__cself) { printf("val=%d\n",__cself-val); }所以,block捕获变量更像是:函数按值传递。
__block int val = 10; void (^blk)(void) = ^{val = 1;};
struct __block_byref_val_0{ void *__isa; __block_byref_val_0 *__forwarding; int _flags; int __size; int val; }
typedef int (^blk_t)(int); for(...){ blk_t blk = ^(int count) {return count;}; }
-(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();
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); }
调用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
static void __main_block_copy_0(struct __main_block_impl_0 *dst, struct __main_block_impl_0 *src){ _Block_objct_assign(&dst->val,src->val,BLOCK_FIELD_IS_BYREF); } static void __main_block_dispose_0(struct __main_block_impl_0 *src){ _block_object_dispose(src->val,BLOCK_FIELD_IS_BYREF); }
int val = 10; void (^blk)(void) = ^{printf("val=%d\n",val);}; val = 2; blk();
上面这段代码,输出值是:val = 10.而不是2.block截获自动变量的瞬时值。因为block保存了自动变量的值,所以在执行block语法后,即使改写block中使用的自动变量的值也不会影响block执行时自动变量的值。
OC高级编程——深入block,如何捕获变量,如何存储在堆上,布布扣,bubuko.com
OC高级编程——深入block,如何捕获变量,如何存储在堆上
原文:http://blog.csdn.net/hherima/article/details/38586101