Objective-C block块与函数指针

block代码块

  • 代码块对象简称为”代码块”,是对 C语言中函数的扩展.运行在 iOS4.0和 OS X 10.6版本以上
  • 代码块实际上是由 C语言实现的,所以在各种以 C 作为基础的语言内都是有效地,其中包括: Objective-C,C++以及 Objective-C++.
  • 代码块不属于 ANSI 的 C语言标准,但是关于代码块的提议已经提交给了美国标准委员会审议.
  • 代码块本质上是和其他变量相似.不同的是,代码块储存的数据是一个函数体.使用代码块时,可以像调用其他标准函数一样,传入参数,并且得到返回值.
  • 因为其定义、调用用法与函数指针基本相似,所以先复习下函数指针的用法
函数指针的语法格式
     void (*pMyFunction)(void);

其中,按照左右法则,先看括号中的未标示的字符, pMyFunction, 其前面有一个*,说明其实一个指针,再往右看是一个括号,则说明其是一个函数指针,名字是 pMyFunction, 后面的参数为空,前面的返回值亦为空.
接下来在 X-Code 中写一个例子来帮助大家理解

#import <Founction/Foundation.h>

//声明了一个数据类型 void (*) (void) 给其去一个别名:pMyFunctionRef
typedef void (*pMyFunctionRef) (void);

//实例化一个对象
pMyFunctionRef pMyFunction;

//声明两个函数
void myFunction(void);
void anotherFunction(void);

int main(int argc,const char * argv[]){
    @autoreleasepool {

        pMyFunction = myFunction;
        //通过函数指针来调用函数
        pMyFunction();

        pMyFunction = anotherFunction;
        pMyFunction();
        //在创建一个函数指针变量,这个指针变量要存放的函数也是返回类型为空,形参是空
        pMyFunctionRef pAnotherFunction;
        pAnotherFunction = myFunction;
        pAnotherFunction();
        // 在这里,有人会说,你吃饱了撑得,直接调用 anotherFunction 就行了嘛其实不然看下面的两种方法,明显的不同第一种直接调用 anotherFunction 函数,再看第二种,把 anotherFunction 当做参数调用,相当于函数调用函数,这样就强大了
        anotherFunction();

        callBack(anotherFunction);
            }
    return 0;
}

//下面的__ fun___ 是 C 中内置的宏,这里的作用的代表这个函数的名字
void myFunction(void){

    NSLog(@"%s",__func__);
}
void anotherFunction(void){

    NSLog(@"%s",__func__);
}
void callBack(pMyFuntionRef fun)
{
    fun();
}
代码块的语法格式

与函数指针类似,主要区别就是*换成了^,而且 block块中还有代码片段,掉用方式基本同函数指针相似.

<returntype> (^blockname)(list of arguments) = ^(arguments){body;};

举一个简单的例子

#import <Founction/Foundation.h>
//定义 myBlock函数,形参是 block 块,返回值为空
//定义的 block 块名 block,形参为空,返回值为空
void myBlcok(void (^blcok)());

int main(int argc,const char * argv[]){
    @autoreleasepool {

void (^theBlcok)();
theBlcok = ^{NSLog(@"I am a block");};
//上面的两句可以用一句表示 void (^theBlock)() = ^{NSLog(@"I am a block");};

//调用块
myBlock(theBlock);

 }
    return 0;
}
void myBlcok(void (^blcok)())
{
    blcok();
}

结果是打印出 I am a block
与函数指针对比一下, 其调用方法都几乎是一样的,改变的是*号变成了^,也就是脱字号,其返回值还可以省略,只不过代码块中的是一段代码而已,可以是一个函数.

再来一个例子,输入几个人的名字,实现名字的排序功能,其主代码如下

NSArray *students = @[@"ZhangSan",@"LiSi",@"WangWu",@"ZhaoLiu",@"MaQi"];
NSLog(@"unsorted array info:%@",students);
//这里使用的NSComparisonResult就是一个 block 块,他是一个枚举类型

NSArray *sortedStudents = [students 
sortedArrayUsingComparator:^NSComparisonResult (id obj1, id obj2) {
                 return [obj1 compare:obj2];}
            ];
NSLog(@"sorted students info:%@",sortedStudents);

其结果是:unsorted array info:(
ZhangSan,
LiSi,
WangWu,
ZhaoLiu,
MaQi
)
2015-06-27 22:03:52.107 BlocksDemo[2990:1834086] sorted students info:(
LiSi,
MaQi,
WangWu,
ZhangSan,
ZhaoLiu
)

代码块的变量
关于代码块局部变量

typedef int (^blockType)(void);
        //关于局部变量

        int myInt = 100;
        int anotherInt = 200;
//        在block内部可以访问和其同一作用域的变量
        blockType blk = ^{return myInt * anotherInt;};
        int result = blk();

        NSLog(@"the result is %d",result);

        myInt = 10;
        anotherInt = 20;
//        在这里根据打印结果来看,其最后的值还是20000,所以说对于block来说, 对于局部变量在其定义的时候实际已经赋值。后续是不能修改的
        result = blk();
        NSLog(@"after modify myInt=10,anotherInt = 20 ther result is %d",result);
关于代码块的全局变量
//声明了一个 block 块的类型,类型的名称是: blockType
typedef int (^blockType)(void);
//关于全局变量

        static int myInt = 100;
        static int anotherInt = 200;
        blockType blk = ^{return myInt * anotherInt;};

        NSLog(@"the result is %d",blk());


        myInt = 10;
        anotherInt = 30;
        NSLog(@"after modify myInt = 10, and anotherInt = 30 the result is %d",blk());

代码一开头就是用了 typedef, 声明了一个block块的类型,类型的名称是:blockType **
以后如果想声明一个block对象用于返回类型是整型,有一个整型参数的block块的时候, 可以使用blockType类型来声明

关于修改代码块外部变量

如果想修改代码块外部的局部变量, 需要在声明这个变量的时候, 用__block来修饰


       //关于修改代码块外部变量
//        int result = 100;

        __block int result = 100; 

        int (^quare_block)(int number) = ^(int number){result =  number * number; return result;};
        NSLog(@"after modify the int result with __block int result:%d",quare_block(20));

__ block 修饰的代码块的局部变量是可以修改的,对于 block 来说, result 是一个外部变量,原先的值是100,用__block 修饰后,在块的代码中修改 result 的值为20 ,输出的结果: after modify the int result with __block int result:400

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值