不引用任何外部变量的 block
- (void)blockDemo1 {
void(^myBlock)() = ^ {
NSLog(@"hello world");
};
NSLog(@"%@", myBlock);
}
不引用任何外部变量的 block 保存在全局区 NSGlobalBlock
如果Block没有引用外部变量,那么这个Block的函数体内部包装的代码都不会发生变化,而且执行效率高,保存在全局区;(类似不变的字符串)
但是实际开发中,不引用外部变量的 block 几乎是不存在的
引用外部变量的 block
- (void)blockDemo2 {
int i = 10;
void(^myBlock)() = ^ {
NSLog(@"hello world %zd", i);
};
NSLog(@"%@", myBlock);
}
引用外部变量的 block 保存在 :
ARC : 堆区 NSMallocBlock
MRC : 栈区 NSStackBlock
因此 : 在定义 block 属性时应该使用 copy 关键字,将 block 从栈区复制到堆区
定义 block 属性
/// 定义 block 属性
@property (nonatomic, copy) void (^demoBlock)();
记录 block 属性
- (void)blockDemo2 {
int i = 10;
void(^myBlock)() = ^ {
NSLog(@"hello world %zd", i);
};
NSLog(@"%@", myBlock);
// 错误的写法,不会调用 setter 方法,MRC下,无法拷贝到堆区
// _demoBlock = myBlock;
// 正确的写法,调用 setter 方法,并且对 block 进行 copy
self.demoBlock = myBlock;
NSLog(@"%@", self.demoBlock);
}
提示 : 为了避免程序员的麻烦,在 ARC 中,定义了引用外部变量的 block,系统默认都是在堆区的!
补充 : 仅做课外了解
演示Block : 分别在MRC和ARC环境下,使用成员变量和属性时的区别
- 此方法是演示MRC环境 (仅做课外了解)
- (void)blockDemo4
{
int num = 10;
void (^task)() = ^ {
NSLog(@"%d",num);
};
// MRC : 栈区 ==> __NSStackBlock__
// 这个赋值过程会copy,也会引用计数+1
// self.task = task;
// 这个赋值过程不会copy,仅仅是引用计数+1,内存依然在栈区
_task = task;
// 在MRC环境下,调用成员变量进行赋值,仅仅是引用计数加1;不会进行copy操作!!!!!
NSLog(@"%@ -- %@",task,_task);
}
- 此方法是演示ARC环境 (仅做课外了解)
- (void)blockDemo3
{
int num = 10;
void (^task)() = ^ {
NSLog(@"%d",num);
};
// ARC : 堆区 ==> __NSMallocBlock__
// ARC环境下,属性也是强引用,同时会copy
// self.task = task;
// ARC环境下,成员变量也是强引用,同时会copy
_task = task;
// <__NSMallocBlock__: 0x7fc24150cae0> -- <__NSMallocBlock__: 0x7fc24150cae0>
// 因为在ARC环境下,上述block本来保存在堆区,给属性赋值的时候,调用setter方法时,会给一个引用;
// 提示 : 在ARC环境下,使用strong和copy的效果是一毛一样的!
NSLog(@"%@ -- %@",task,_task);
}