作者:Love@YR
链接:http://blog.csdn.net/jingqiu880905/article/details/50685683
请尊重原创,谢谢!
block 有三种类型 NSConcreteGlobalBlock、_NSConcreteStackBlock、_NSConcreteMallocBlock
分别存储在数据区,内存栈区,内存堆区
那么什么时候存储在哪个区上呢?我们看看下面的例子。
#import "ViewController.h"
static NSString *globalStr=@"global";
typedef void (^blk_t)(int);
@interface ViewController ()
{
}
@end
@implementation ViewController
。。。省略
- (IBAction)buttonTaped:(id)sender {
int *a2;
__block int b2;
b2=3;
a2=&b2;
static NSString *localStr=@"local";
//未引用外部变量即为NSGlobalBlock
blk_t bl1=^void(int a){
localStr=@"localstr1";//局部静态变量,通过指针传递
globalStr=@"globalStr1";//全局静态变量和全局变量,通过值传递
NSLog(@"a is %d,local str is %@,global str is %@",a,localStr,globalStr);
};
NSLog(@"bl1 is at %@",bl1);
blk_t bl2=^void(int a){
localStr=@"localstr1";//局部静态变量,通过指针传递
globalStr=@"globalStr1";//全局静态变量和全局变量,通过值传递
b2=6;//局部变量,b2需要__block修饰 不然只可读
NSLog(@"a is %d,a2 is %d,b2 is %d,local str is %@,global str is %@",a,*a2,b2,localStr,globalStr);
};
//引用了外部变量即为stack block,block的实现与上面的完全相同
NSLog(@"bl2 block is %@",^void(int a){
localStr=@"localstr1";//局部静态变量,通过指针传递
globalStr=@"globalStr1";//全局静态变量和全局变量,通过值传递
b2=6;//局部变量,b2需要__block修饰 不然只可读
NSLog(@"a is %d,a2 is %d,b2 is %d,local str is %@,global str is %@",a,*a2,b2,localStr,globalStr);
});
//引用了外部变量即为stackblock,arc下当引用此block变量时自动复制到堆上
NSLog(@"bl2 is %@",bl2);
bl1(5);//调用
bl2(10);//调用
}
@end
打印的结果:
bl1 is <__NSGlobalBlock__: 0x10f13c0d0>
bl2 block is <__NSStackBlock__: 0x7fff50ac3078>
bl2 is <__NSMallocBlock__: 0x7fc81bf21aa0>
a is 5,local str is localstr1,global str is globalStr1
a is 10,a2 is 3,b2 is 6,local str is localstr1,global str is globalStr1
参考:http://www.cnblogs.com/hanjun/p/3767394.html
https://blog.csdn.net/jingqiu880905/article/details/51997126
bl1里的变量a是其作用域里的局部变量,而静态局部变量和静态全局变量还有非静态的全局变量都是存储在静态(全局)数据存储区分配即global
不使用arc的话,引用栈block是不会自动复制到堆上的
使用arc的话,引用栈block会复制到对上
注意: 这里的引用是强引用 即前面没有__weak __assign这种关键字的。如果前面加了__weak 那么指向的block还在栈上并不会复制到堆上