您的位置:首页 > 移动开发 > Objective-C

【Objective-C】代码块(Block)

2015-08-14 10:46 417 查看
一、Block是什么?

1. 是代码段,苹果推荐的类型,效率高,在运行中保存代码。用来封装和保存代码,有点像函数,block可以在任何时候执行;

2. 代码块本质上是和其他变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值。

脱字符(^)是块的语法标记。按照我们熟悉的参数语法规约所定义的返回值以及块的主体(也就是可以执行的代码)。下图是如何把块变量赋值给一个变量的语法讲解



按照调用函数的方式调用块对象变量就可以了:

int result = myBlock(4); // result是 28

3. 和函数的相似性:

1)可以保存代码;

2)有返回值

3)有形参

4)调用方式一样

4. 标识符:^

二、基本使用

1. 定义block变量

Int (^SumBlock)(int,int);//有参数,返回值类型为int

Void (^MyBlock)();//无参数,返回值类型为空

2. 利用block封装代码

// 利用block封装代码
        // 1.接受两个参数
        int (^MyBlock1)(int, int) = ^(int a, int b) {
            return a + b;
        };
        
        // 2.无参数形式
        int (^MyBlock2)() = ^() {
            return 20;
        };
        
        // 3.无参数的省形式
        // 2.无参数形式
        int (^MyBlock3)() = ^ {
            return 20;
        };
3. Block访问外部变量

1)Block内部可以访问外部变量;

2)默认情况下,Block内部不能修改外部的局部变量

3)给局部变量加上__block关键字(两个下划线哦),则这个局部变量可以在block内部进行修改。

如:
void test2() {
    __block int c = 19;
    
    // 声明一个block变量
    // 可以使用无数多个变量进行调用
    MySum sum = ^(int a, int b) {
        // 如果外部的变量已经用__block关键字修饰,就可以在block内部修改这一个变量
        c = 19;
        return  a + b;
    };
    NSLog(@"%i", sum(10, 10));
}
4. 利用typedef定义block类型(和指向函数的指针很像)。关于tepedef的作用后面的的文章有介绍typedf讲解

Typedef int(^MyBlock)(int , int);

以后就可以利用这种类型来定义block变量了。----使用这个好处就是:可以使用无数多个变量进行调用(如下面定义了两个变量),传统的方式只能定义一个变量

MyBlock a, b;

a = ^(int a,int b){return a-b;};
MyBlock b2 = ^(int n1,int n2){return n1*n2;}

三、拓展案例

1. 参数是NSString* 的代码块

void (^print)(NSString *x);
        print = ^(NSString *str){
            NSLog(@"print:%@", str);
        };
        
        print(@"Hello World");
2. 代码在字符串数组排序
// 字符串
        NSArray *str = [NSArray arrayWithObjects:@"abc 1", @"abc 22", @"abc 13", @"abc 0", @"abc 09", nil];
        NSComparator sort = ^(id str1, id str2) {
            return [str1 compare:str2];
        };
        
        NSArray *sortArray = [str sortedArrayUsingComparator:sort];
        NSLog(@"sortArray:%@", sortArray);
结果是:

@class关键字[598:144356] sortArray:(

"abc 0",

"abc 09",

"abc 1",

"abc 13",

"abc 22"

)

3. 代码块要想递归调用,代码快变量必须要是全局变量或者是静态变量,这样程序启动的时候代码块变量就初始化了,就可以递归调用
static void (^ const blocks)(int) = ^(int i)  
{  
    if (i > 0) {  
        NSLog(@"num:%d", i);  
        blocks(i - 1);  
    }  
};  
blocks(3);
4.在代码块中使用局部变脸和全局变量
int global = 1000;  
int main(int argc, const char * argv[])  
 {  
      @autoreleasepool {  
         void(^block)(void) = ^(void)  
         {  
            global++;  
             NSLog(@"global:%d", global);  
         };  
         block();  
         NSLog(@"global:%d", global);  
     }  
     return 0;  
 }
局部变量要想再代码块中能够更改的话需要在block里面添加一个__(两个下划线)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: