block

block封装了一段代码,可以在任何时候执行,block可以作为函数参数或者函数的返回值,而其本身又可以带参数或返回值,所以有时候称block为代码块或代码段。

 

 1.block的定义:这里跟指向函数的指针非常像,但是一般需要使用指向函数的指针的时候都是用block替代,能用block就用block(苹果官方建议)

 

    int (^MyBlock)(int, int);

    MyBlock = ^(int a, int b) {

        return a + b;

    };

 

 实际上可以直接这么写

    int (^MyBlock)(int, int) = ^(int a, int b) {

                return a + b;

        };

 

 定义了一个叫MyBlock的block对象,它带有两个int参数,返回值类型int,等式的右边就是block的具体实现

 返回值类型(^block代码块名称)(接受参数类型1,接受参数类型2) = ^(形参1,形参2){

 返回值

 };

 

 2.block的typedef

    语法:与函数的typedef类似

    typedef 返回值类型 (^block代码块别名)(参数类型列表);

    这里要记住的是 这里的代码块别名指的是类型

    例如:

    //给无返回值、带2个int类型参数的block类型起别名isBlock

    typedef void(^isBlock)(int,int);

    //利用别名 定义变量 myBlock,并将代码段赋值给myBlock

    isBlock myBlock = ^(int a,int b){

 

            NSLog(@"a + b = %d",a+b);

    };

 

 3.三种类型的block

    1)NSGlobalBlock,类似函数存放在代码区

        定义在函数外的(全局)block是NSGlobalBlock类型的,另外如果函数内部的block没有访问任何函数内部局部变量,那么也是NSGlobalBlock类型的

 

    2)NSStackBlock,存放在栈区,代码块结束后(作为函数返回值)block将无效

        在MRC情况下函数内部的block访问局部变量,得到的是栈区

 

    3)NSMallocBlock,存放在堆内存

    在MRC情况下,对栈区的block进行copy,才会得到一个堆区的block,要注意的是,对全局block进行copy,不会有任何作用,依然是代码区block

    在ARC情况下,访问局部变量,得到的是堆区的block,对堆区的block进行copy,依然是堆区

 

 4.block作为实例变量@property为什么要使用copy

    因为在MRC情况下使用block(栈区的block)作为函数返回值,block存放在栈区,代码结束,也就被回收了,返回的是无效的block,同理,作为方法参数,block其实是在堆区指向栈区的一块内存中存放,也存在作用域的问题.在ARC的情况下没有这个内存隐患

 1 #import <Foundation/Foundation.h>
 2 
 3 int main(int argc,const char * argv[]){
 4     @autoreleasepool {
 5     
 6     //创建一个block,没有访问函数内部局部变量
 7     void (^isBlock1)() = ^(){
 8         NSLog(@"我是没有访问局部变量的block");
 9     };
10     
11     //ARC情况下输出:isblock1的内存地址是:<__NSGlobalBlock__: 0x100001060>
12     //代码区
13     NSLog(@"没有访问局部变量的block内存地址是:%@",isBlock1);
14         
15     //MRC情况下输出:isblock1的内存地址是:<__NSGlobalBlock__: 0x100001050>
16     //代码区
17     NSLog(@"没有访问局部变量的block内存地址是:%@",isBlock1);
18     
19     int a = 10;
20         
21     void (^isBlock2)() = ^(){
22             NSLog(@"我是访问局部变量的block,%d",a);
23         };
24     //ARC情况下输出:isblock2的内存地址是:<__NSMallocBlock__: 0x1002067c0>
25     //堆区
26     NSLog(@"访问局部变量的block内存地址是:%@",isBlock2);
27     
28     //MRC情况下输出:isblock2的内存地址是:<__NSStackBlock__: 0x7fff5fbff808>
29     //栈区
30     NSLog(@"访问局部变量的block内存地址是:%@",isBlock2);
31         
32     //在MRC情况下对刚才访问局部变量的isBlock进行copy操作
33     void (^isBlock3)();
34     isBlock3 = [isBlock2 copy];
35     //MRC情况下输出:copy后内存地址是:<__NSMallocBlock__: 0x1002067c0>
36     //堆区
37     NSLog(@"copy后内存地址是:%@",isBlock3);
38         
39     }
40     
41     return 0;
42 }

 

posted on 2015-07-16 23:14  lizzie8023  阅读(266)  评论(0编辑  收藏  举报