-----------------------------------------------欢迎查看block连载博客【专栏】-----------------------------------
【block编程第一篇】block语法 【block编程第二篇】block捕获变量和对象;
【block编程第三篇】block的内存管理(当前) 【block编程第四篇】block内部实现;
【block编程第五篇】block中如何避免循环引用
------------------------------------------------------------------------------------------------------
Block存储区域
-----【要点1】:全局block
typedef int (^blk_t)(int);
for(...){
blk_t blk = ^(int count) {return count;};
}
--【要点2】:栈block
typedef void (^block_t)() ;
-(block_t)returnBlock{
__block int add=10;
return ^{printf("add=%d\n",++add);};
}
-(block_t)returnBlock{
__block int add=10;
block_t blk_h =^{printf("add=%d\n",++add);};
return blk_h;
}
block_t bb = [self returnBlock];
bb();
这段代码,只是使用了一个自动block变量,可以编过,但是造成程序崩溃了。
如果在返回block的时候加上copy,可以输出正确的数值11
--【要点3】:堆上的block
-(id) getBlockArray{
int val =10;
return [NSArray arrayWithObjects:
^{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();
--【要点4】copy的使用
--【对《Objective-C 高级编程》的挑战】
-(void) stackOrHeap{
__block int val =10;
blkt1 s= ^{
return ++val;};
s();
blkt1 h = [s copy];
h();
}
在非ARC和ARC下,调试结果如下:
【第二个方法】,声明一个局部变量指针。通过指针来看
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
在非ARC下>>>>>>>>>确实复制到堆上了。 val_block = 11 valPointer = 10
---【总结】---
-(id)getBlockArray{
int val = 10;
NSArray *arr = [NSArray alloc] initWithObjects:^{NSLog(@"blk0:%d",val);},
^{NSLog(@"blk1:%d",val);},
^{NSLog(@"blk2:%d",val);},nil];
return arr;
}
如果使用了array中的block就会crash(使用第1个block才会crash,第0个不会crash,不解啊!)。此时block还在栈上。