Block介绍及使用

在实际开发中,使用Block比delegate和notification更简洁。于是在项目中会大量的使用block。

1、什么是block?

block其实就是一个代码块,将要执行的代码封装在这个代码块里面,等到需要的时候再去调用。block也是OC对象,官方文档如下

image

2、block要用copy修饰,还是用strong

block本身是像对象一样可以retainrelease。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。

  • 使用retain也可以,但是blockretain行为默认是用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。
(__blockARCMRC均可以使用,__weak只能在ARC下使用)
如果你使用的是ARC,那么就应该改成下面这样:

__weak CurrentViewController* blockSelf = self;  
brush.getCardInfo=^(NSDictionary *info){  
        [blockSelf test];  
};  

你可能感兴趣的:(Block介绍及使用)