在实际开发中,使用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];
};