block快的存储位置(block入口的地址)可能存放在3个地方:代码区(全局区)、堆区、栈区(ARC情况下回自动拷贝到堆区、因此ARC下只有两个地方:代码区和堆区)
有三种常见的类型:
①<NSGlobalBlock: 0x102cef0b8>
存储在程序的代码段,全局区;NSGlobalBlock:不会访问任何外部变量,比如:
void(^blockA)(void) = ^{
NSLog(@"just a block");
};
NSLog(@"%@", blockA);
②<NSMallocBlock: 0x60000025b120>
存储在堆上。当blcok的引用计数为0时会被销毁,比如:
int value = 10;
void(^blockB)(void) = ^{
NSLog(@"just a block === %d",value);
};
NSLog(@"%@", blockB);
③<NSStackBlock: 0x7ffeecf0fad0>
存储在栈上,NSStackBlock:在block内部引用外部变量,除了函数作用域会被销毁,引用导致奔溃,所以需要拷贝到堆上,比如:
// 强行在ARC上将一个block创建在栈上
void(^__weak blockC)(void) = ^{
NSLog(@"just a block === %d",value);
};
NSLog(@"%@", blockC);
//注意:在arc情况下,没有NSStackBlock这个类型,如果有系统自动copy成为NSMallocBlock,同时会拷贝代码内部变量如:
int base = 2;
base += 2;
long (^sums)(int,int) = ^ long (int a,int b){
return base + a + b;
};
base ++;
NSLog(@"%ld",sums(1,2));
//输出的结果为 7 arc下提前拷贝base
需要特别注意的是,在ARC下,很多都已经自动帮我们Copy成了MallocBlock了,由于Block是默认建立在栈上,所以如果离开方法作用域就会释放,如果要在外部调用,需要用copy指向它,这样就拷贝到了堆区,strong不具有拷贝功能