首页 > 技术文章 > 关于 block的一些浅识

zhidao-chen 2014-03-12 16:47 原文

block的定义:“带自动变量的匿名函数”

(一)写法: 

^ void (int iAge){ NSLog(@"%d", iAge);};

和C函数写法区别在于:

1) :以插入符号 ^ 开始.

2):没有函数名字

当block声明变量时候的写法

void (^blk)(int iAge)

block 做函数参数时候 

void testFunction:(int)age complete:(void(^)(int iAge))complete{
  age++;
  if(complete){
    complete(age);
 }    
}

(二)block是c语音的扩展,实际上block会被翻译成c语言的static 结构体和static方法,这就是为什么block能截获自动变量的原因。

-(id)init{
    if (self = [super init]) {
        int iTmp = 0;
        ^(int i){
            iTmp = 10;
        };
    }
    return self;
}

修改变量编译报错 修改为
-(id)init{
    if (self = [super init]) {
       __block  int iTmp = 0;
        ^(int i){
            iTmp = 10;
        };
    }
    return self;
}

 

(三)关于block循环引用导致内存泄漏

   1):block中使用到类的strong类型变量以及使用到self ,会导致内存泄露。一般解决办法

      a:开启ARC 使用__weak 临时变量做转存。

@interface MyTest:NSObject{
   strong id param;  
}
- (id)init{ if(self = [super init]){ ^(){ NSLog(@"%@", self); NSLog(@"%@", param);//XCode也会报告警告的,提示有循环引用 } } } //修改如下 - (id)init{ if(self = [super init]){ __weak id tmp = param; __weak id selfTmp = self; ^(){ NSLog(@"%@", selfTmp); NSLog(@"%@",tmp);//XCode也会报告警告的,提示有循环引用 } } }

 

      b:若ARC关闭了,可使用__block类型临时变量,再在block中把临时变量赋值为nil,只是必须调用该block,不然一样会内存泄漏

- (id)init{
   if(self = [super init]){
   __block id tmp = param;
    void (^blk)() = ^(){
       NSLog(@"%@",tmp);
     tmp = nil;
      }
   }
}    

循环引用的原因在于有strong 修饰的自动变量会被复制到堆上,copy.

在关闭ARC,需要手动 Block_copy() block 和Block_relase()

推荐阅读