1.block不调用外界变量的情况
- (void)touchesBegan:(NSSet *)touches withEvent: (UIEvent*)event {
//类型变量名=值;
intage = 100;
NSLog(@"====%p",&age);栈区
//没有参数没有返回值的block
void(^block)() = ^{
NSLog(@"我是block = %p",&age);堆区
};
//执行block
block();
[selftestBlock:block];
NSLog(@"====%p",&age);栈区
}
- (void)testBlock:(void(^)())block {
block();
}
2.通过__block调用外部变量的情况
总结:只要通过__block修饰以后,外部变量的地址就变为堆区,在调用blcok之前值还是栈区的值,而地址在堆区,当调用了block以后,值变为修改后的值,而地址也在堆区
/**
* block修改外部变量`
*/
- (void)testBlock5 {
//类型变量名=值;
__block intage = 100;
NSLog(@"====%p",&age);//栈
//使用__block修饰外部变量时,在定义完成block之后,栈中的外部变量就是一个摆设,没有什么乱用了
void(^block)() = ^{
age = 200;
NSLog(@"block中的age = %d",age);// 200
NSLog(@"我是block = %p",&age);//堆
};
使用__block修饰以后,但是没有调用block时候,值不改变,但是地址保存到堆区了
NSLog(@"====%p",&age);//堆
NSLog(@"age =%d",age);// 100
//执行block
//使用__block修饰以后,调用了block以后,值改变,地址也保存到堆区了,
block();
NSLog(@"====%p",&age);//堆
NSLog(@"age =%d",age);// 200
}
**结语: **
1.block的三种类型:
全局block :(打印出来__NSGlobalBlock)
无论是ARC还是MRC情况下:block内部没有访问任何外部变量时,block就是全局block
或者访问的是static修饰的静态变量的时候,就是全局block
堆block: (打印出来是__NSMallocBlock)block内部访问我外部变量时,(不为静态变量时,).block是堆区block
在MRC环境下,给block调用copy方法,会将栈block拷贝到堆中
C.栈block :(打印出来是__NSStackBlock)
在MRC情况下,block内部访问外部变量时(不为静态变量),block是栈区block
为什么block要用copy修饰,因为不用copy修饰,当MRC模式 下,block内部访问外部属性时(且属性不为静态属性时),block是栈区block,这样外界调用的时候,就会报错,使用copy,我们的block无论是ARC还是MRC情况下,肯定是堆区block,外界调用就不会有影响
所以block使用copy是为了兼容MRC的情况,因为很多项目是ARC和MRC混编.