OC中对Block理解

一般书上介绍block,都是说block是一个闭包,搞不懂什么是闭包,当做这是一个名词就好。


本文介绍一下block的以下几个方面:

1.block是什么?

2.block的用法

3.栈block 堆block 全局block


1.block是什么

   block使用起来像是一个函数指针,但实际在内存中的存储结构像是一个类。

   block的内存模型如下:

Class 指针isa
函数指针fun
变量池 
  

  上面表格中,isa指针指向的就是类的具体类型指针。函数指针fun就是block的执行函数。变量池中保存的都是block函数中所用到的变量的指针地址,例如block函数体中调用了self得某个方法,则变量池中就是保存指向self的指针。

   这个内存模型和常规的对象模型又不太一样,所以我将block理解成为只含有一个方法的对象,切对象中得变量是动态增加,减少的。

  block在程序中作用非常大,一般我在编程用得最多的就是在http请求中,因为网络请求是一个异步执行的过程,当网络请求成功(失败)时,就会调用相应的block函数。


2.block的用法
   block用法的定义如下:
    
returnType (^blockName)(parameter){}

  例: 

  一般用法:

//定义一个block
int (^max)(int a,int b);


//给这个block赋值
max = ^(int a,int b){
    return a>b?a:b;
}


//使用block
int m = max(3,5)   //m=5   

   如果需要在block内改变外部变量的数值,则外部变量必须在定义时,前面加上__block关键字

    

__block int amount = 0;
void (^addAmount) = ^{
   amount += 1;
}
NSLog(%d,amount) //amount = 1;
//如果不加__block关键字,则数值在block内无法改变

    常规用法:

    将block应用在某一函数中,我平时最常用的是网络请求,请求成功,失败都可以用block来实现回调

    

//用typedef定义两个block

typedef void(^completeSuccess)(id responseObject);

typedef void(^completeFailure)(NSError *error);
..........
//定义类中的方法
void getToken:(completeSuccess) success error:(completeFailure)error;
//如果返回成功,可以用success来存储服务器返回的报文,失败则用error来保存错误报文。

   注意事项:

   因为Block中会持有变量,这样就有可能在block内引起双向引用。

    

//在block内调用self方法
void (^someBlock) = ^{
     
    [self someMessage];
}
//以上可能会引起双向引用,self内有block指针,block内持有self指针(保存在常量池中)。

//正确的用法是
__weak id weakSelf = self;
void (^someBlock) = ^{
     
    [weakSelf someMessage];
}

3.栈block,堆block和全局block
1)堆栈block

      看一个例子:
       
//定义一个block
void (^outPut)(void);
if(...){
  
  outPut = ^{
    NSLog("output one!");
}    
}
else{
   
    outPut = ^{
      NSLog("output two!");
}
}

以上这段代码,执行后,会出现有时执行正确,有时执行错误的情况。
这是因为,在if,else中block是分配在栈内存中的,如果编译器将其他代码分配到同一块栈内存时,则block失效。

要解决这个问题,可以在分配时,加上copy关键字,这个时候就能将栈内存中得数据转移到堆内存中,堆内存中的数据,当retainCount为0时,才释放。
outPut = [^{
  NSLog("outPut one");
} copy];

2)全局block

   


如果有任何问题欢迎再下面留言,或者扫描二维码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值