block 顾名思义就是代码块,将同一逻辑的代码放在一个块,使代码更简洁紧凑,易于阅读,而且它比函数使用更方便,代码更美观,因而广受开发者欢迎。但同时 block 也是 iOS 开发中坑最多的地方之一,因此有必要了解下 block 的实现原理,知其然,更知其所以然,才能从根本上避免挖坑和踩坑。
需要知道的是,block 只是 Objective-C 对闭包的实现,并不是 iOS 独有的概念,在 C++、Java 等语言也有实现闭包,名称不同而已。
Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的
Block的定义格式
返回值类型(^block变量名)(形参列表) = ^(形参列表) {
};
调用Block保存的代码
block变量名(实参);
typedefvoid(^BlockType)(int);
//声明属性
@property (copy) BlockType myBlock;
@property (nonatomic, copy) void(^textBlock) (NSString*text); // 字符串回调
@property (nonatomic,copy)dispatch_block_t blockAction; // 点击事件回调
回调值
__weaktypeof(self) weakSelf =self;
vc.v= ^(NSString*str){
weakSelf.textStr=str;
};
//有了atomic来保证基本的原子性还是没有达到线程安全的,调用时需要把Block先赋值给本地变量,以防止Block突然改变。即便是先判断了Block属性不为空,在调用之前,一旦另一个线程把Block属性设空了,程序就会crash:
if(self.myBlock)
{
self.myBlock(123);
}
//先判断其是否为空,self.myBlock可能被另一个线程改为空,造成crash
//注意:atomic只会确保myBlock的原子性,这种操作本身还是非线程安全的
注:循环引用问题
在ARC下,由于__block抓取的变量一样会被Block retain,所以必须用弱引用才可以解决循环引用问题
__weaktypeof(self) weakSelf =self;
self.myBlock= ^()
{
};