Objective-C中的Block(基础)

基本语法

定义的语法格式:

^ [块返回值类型] (形参类型1 形参1, 形参类型2 形参2, ...){
    //块执行体
}

定义块的语法与定义函数的语法存在如下差异:

  • 定义块必须以^开头;
  • 定义块的返回值类型可以省略;
  • 定义块无须指定名字;
  • 如果块没有参数,参数部分的括号不可省略,但可以留空,建议以void作为占位符。

若需多次调用已经定义的块,可定义一个块变量,将该块赋给块变量,通过块变量来调用块。定义块变量的格式:

块返回值类型 (^块变量名) (形参类型1, 形参类型2, ...);

块与匿名函数类似,块变量与函数指针类似。

块与局部变量

  1. 对于没有用__block修饰的局部变量,块只能访问它,但不可修改它;且在定义块时就已经将这种局部变量的值保存在块中,而不是等到调用块时才去访问、获取它的值,因此,后续程序对局部变量的值的修改,对块没有影响,即便这种修改在调用块之前。
    #import <Foundation/Foundation.h>
    int main(){
        @autoreleasepool{
            int my = 20;
            void (^printMy)(void) = ^(void){
                //尝试对局部变量赋值,程序会报错
                my = 30; // ①
                NSLog(@"%d", my); //访问局部变量是可以的
            };
            my = 45;
            printMy(); //调用块
        }
    }
    

    将①处代码注释掉,再编译运行上述程序,会输出20,而非45。

  2. 对于__block修饰的局部变量,块内可以修改它;并且,无论何时,块都会直接使用该局部变量本身,而不是将局部变量的值复制到块内。
    #import <Foundation/Foundation.h>
    int main(int argc, char* argv[]){
        @autoreleasepool{
            __block int my = 20;    
            void (^printMy)(void) = ^(void){
                NSLog(@"%d", my);
                my = 30;
                NSLog(@"%d", my);
            };    
            my = 45;
            printMy();
            NSLog(@"%d", my);
        }
    }
    

    上述程序三次分别输出45、30、30。

块作为函数参数

块作为函数参数时,无需定义块变量,直接把块作为参数传递给函数即可。出于可读性考虑,通常将块作为函数的最后一个参数。

使用typedef定义块类型

语法格式:

typedef 块返回值类型 (^块类型)(形参类型1 [形参名], 形参类型2 [形参名], ...);

用途:

  1. 复用块类型,使用块类型可以更方便地定义块变量;
    #import <Foundation/Foundation.h>
    int main(int argc, char* argv[]){
        @autoreleasepool{
            //定义了一个返回类型为void、形参为NSString*的块类型FKPrintBlock
            typedef void (^FKPrintBlock)(NSString*);
            //使用块类型定义块变量,并将指定块赋给块变量
            FKPrintBlock print = ^(NSString* info){
                NSLog(@"%@", info);
            };
            //使用块类型定义块变量,并将指定块赋给块变量
            FKPrintBlock loopPrint = ^(NSString* info){
                for(int i = 0; i < 3; ++i){
                    NSLog(@"%@", info);
                }
            };
            //一次调用两个块
            print(@"Objective-C");
            loopPrint(@"iOS");
        }
    }
    
  2. 使用块类型定义函数参数。
    #import <Foundation/Foundation.h>
    typedef void (^FKProcessBlock)(int); //定义一个块类型
    //使用FKProcessBlock定义最后一个参数类型为块
    void processArray(int array[], unsigned int len, FKProcessBlock process){
        for(int i = 0; i < len; ++i){
            //将数组元素作为参数调用块
            process(array[i]);
        }
    }
    int main(int argc, char* argv[]){
        @autoreleasepool{
            int arr[] = {2, 4, 6};
            //传入块作为参数调用processArray()函数
            processArray(arr, 3, ^(int num){
                NSLog(@"元素平方为:%d", num * num);
            });
        }
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客熊猫GeekPanda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值