iOS Block

Block

什么是block

能够截获自动变量的匿名函数,匿名函数也就是不带函数名的函数

block语法

^ 返回值类型 (参数列表){ 表达式 }

   ^int (int test){
        return test;
    };
  • 当返回值类型为空时我们可以将返回值类型那一项省略或者写成void

^ (参数列表) { 表达式 }

^ void (参数列表) { 表达式 }

 //返回值为空
    ^ (int test){
        printf("%d",test);
    };
    
    ^void (int test){
        printf("%d",test);
    };
  • 当参数列表为空是我们也可以将其省略或写成void

^ void { 表达式 }

^ void (void) { 表达式 }

    ^{
        printf("hello world!");
    };
    
    ^void (void){
        printf("hello world!");
    };

 block类型变量的声明

返回值类型 (^变量名) (参数列表);

//声明一个返回值为 int 类型,有一个 int 类型参数的block 
int (^block) (int);
//给上面声明的block类型变量赋值
 block = ^int (int test){
        printf("%d",test);
        return test + 1;
    };

 用typedef定义block

在使用block时,对于相同返回值相同参数的 block 变量我们可能会多次使用到,如果每次使用的时候都声明一次会比较麻烦,这个时候我们就可以使用 typedef 来定义 block。

   //定义一个返回值,参数列表都为空的block类型,名为voidBlock
    typedef void(^voidBlock)(void);
    //声明一个 voidBlock 类型的变量
    voidBlock block = ^(){
        NSLog(@"voidblock");
    };
    block();

截获自动变量

    int a = 1;
    void (^block) (void) = ^{
        NSLog(@"block a = %d",a);
    };
    a += 1;
    block();
    NSLog(@"%d",a);

上述代码的打印结果为

2018-10-13 12:29:46.903008+0800 block[966:985286] block a = 1
2018-10-13 12:29:46.903157+0800 block[966:985286] 2

block能够截获其代码块中所使用的自动变量的值,它会保存该自动变量的瞬间值。由于它保存的是自动变量的瞬间值,所以在执行 block 语法后再去改变该变量的值并不会对 block 中所使用的变量值产生影响。

__block 说明符

  • block 只能截取保存自动变量的瞬间值,而不能修改该变量
    int a = 1;
    void (^block) (void) = ^{
        a = a + 1;
    };
    block();

以上代码在 block 中改变了变量 a 的值,我们会发现这样的代码会发生编译错误

Variable is not assignable (missing __block type specifier)

  • 如果要在block中修改自动变量的值,我们需要用 __block 修饰该变量
        __block int a = 1;
        void (^block) (void) = ^{
            a = a + 1;
            NSLog(@"block a = %d",a);
        };
        block();
        
        //这段代码的执行结果为block a = 2

     

  • 上面我们提到block会保存自动变量的瞬间值,从而在执行 block 语法后再去改变该变量的值并不会对 block 中所使用的变量值产生影响,但是如果使用 __block 修饰该自动变量,则该变量的值可以发生改变。
  •  __block int a = 1;
        void (^block) (void) = ^{
            NSLog(@"block a = %d",a);
        };
        a += 1;
        block();
        NSLog(@"%d",a);

    上述代码的执行结果为,block 中 a 的值是改变后的值

    2018-10-13 17:05:11.004404+0800 block[2677:3608745] block a = 2
    2018-10-13 17:05:11.004553+0800 block[2677:3608745] 2

     

  • block 与 OC 对象,在 block 中不能直接给 OC 对象赋值,但是可以调用改变的该对象的方法。例如:
        NSMutableArray *array = [NSMutableArray array];
        void (^block) (void) = ^{
            [array addObject:@"block"];
            NSLog(@"%lu",(unsigned long)array.count);
        };
        block();

    上述代码的执行结果

    2018-10-13 17:12:37.390769+0800 block[2748:3689145] 1

    这是因为在block中,截获的自动变量 array 是对象指针,该指针指向 NSMutableArray 对象,执行 [array addObject:@"block"] 并没有直接改变该指针变量的值,所以该操作是合法的。但是不可以直接给 array 赋值,否则会发生编译错误。例如以下代码就会发生编译错误:

        NSMutableArray *array = [NSMutableArray array];
        void (^block) (void) = ^{
            array = nil;
        };
        block();

     

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值