在实际开发中,使用Block比delegate和notification更简洁。于是在项目中会大量的使用block。
1、什么是block?
block
其实就是一个代码块,将要执行的代码封装在这个代码块里面,等到需要的时候再去调用。block
也是OC对象,官方文档如下
2、block要用copy修饰,还是用strong
block
本身是像对象一样可以retain
和release
。但是,block
在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上
。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。
- 使用
retain
也可以,但是block
的retain
行为默认是用copy
的行为实现的,
因为block
变量默认是声明为栈变量
的,为了能够在block
的声明域外使用,所以要把block拷贝(copy)到堆
,所以说为了让block属性声明和实际的操作一致
,最好声明为copy
。
3、__block关键字的使用
在Block
的代码块内不可以对外面的变量
进行更改的,使用__block
就能改变block
代码块中变量
的值
4、__block和__weak有什么区别?
-
__block
不管是ARC
还是MRC
模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。 -
__weak
只能在ARC
模式下使用,也只能修饰对象(NSString)
,不能修饰基本数据类型(int)
。 -
__block对象
可以在block
中被重新赋值
,__weak
不可以。
5、Block的使用
@interface BrushViewController : BaseViewController
@property (nonatomic, copy) void (^getCardInfo)(NSDictionary *cardInfo);
@end
将block
声明为copy
的原因是在代码块里面我可能会使用一些本地变量
。而block一开始是放在栈上的,只有copy后才会放到堆上。
如果不加copy
属性,当其所在栈被释放的时候,这些本地变量将变得不可访问。一旦代码执行到block内部
就会出错。
brush.getCardInfo=^(NSDictionary *info){
[self test];
};
像上面这段代码,self
是一个本地变量
而不是block内部变量
,如果声明为assign
,代码执行到block内部
就会出错。
另外一个问题就是self
的引用计数会+1
。这样会导致循环引用
。self持有brush,brush持有block,block持有self,结果就是内存泄漏
。
解决的办法如下:
__block CurrentViewController* blockSelf = self;
brush.getCardInfo=^(NSDictionary *info){
[blockSelf test];
};
通过这个方式,告诉block这个变量的引用计数不要+1。
(__block
在ARC
和MRC
均可以使用,__weak
只能在ARC
下使用)
如果你使用的是ARC
,那么就应该改成下面这样:
__weak CurrentViewController* blockSelf = self;
brush.getCardInfo=^(NSDictionary *info){
[blockSelf test];
};