一、C的函数指针
block语法和 C语言的函数指针相似,先看看函数指针是是怎么一回事
1. 概述
C语言可以把函数名作为函数指针处理,函数指针就是存放函数代码的首地址
2.声明函数指针
例如有一函数原型如下
int funA(double, int *);
声明指向该函数的函数指针int (*p)(double, int *);
上述语句就声明了一个名为 p 的函数指针,该函数指针指向一个 返回类型为 int,两个参数分别为 double 和 int * 的函数也可以使用 typedef 来声明一个类型,假设新的类型名为 t_func
typedef int (*t_func)(double, int *);
上述语句就声明了一个名为 t_func 的类型,该类型是一个 指向函数的函数指针类型3. 通过函数指针调用函数
先声明一个函数指针类型的变量
t_func fptr = funA; // funA 是一个函数指针,指向返回为 int,两个参数为别为 double 和 int * 的函数
有两种方法调用第一种 :
int x = (*fptr)(3.14, &i);
第二种 :int x = fptr(3.14, &i);
推荐使用第一种写法,因为如果存在同名的函数(fptr),就有可能发生冲突
二、OC 的 block 语法
1. 概述block 语法(也叫 block 对象)就是没有没有名称的函数,即匿名函数,它是把一个匿名函数定义为一个对象
2. 语法格式
声明一个 block 对象
int (^myBlock)(int, int);
上述声明的 block 对象名为 myBlock,结合 C 的函数指针,myBlock 指向一个匿名函数(此函数返回 int,并且有两个参数均为 int 型)定义一个 block 对象,给 block 对象赋值,赋的值是一个匿名函数
int (^myBlock)(int i, int j) = {
return i * j;
};
定义一个名为 myBlock 的块对象,该块对象指向一个匿名函数(此函数返回传入两个参数的乘积)注意 : 声明 block 块对象时,必须带有 “^” 符号;定义匿名函数时,必须以 “^” 开头,紧接着是函数参数列表,再是函数体
3. typedef 与 block
typedef 与 block 和 typedef 与 函数指针类似
定义一个新的类型,名为 t_block
typedef int (^myBlock)(int, int);
上述语法声明的是一个名为 t_block 的类型,不再是对象,所以此时声明该类型的对象时是要赋值的,赋的值是匿名函数使用新类型定义对象
myBlock demoBlock = ^(int a, int b) {
return a + b;
};
定义了一个名为 demoBlock 的块对象,该块对象指向一个返回两个参数的和的函数4. block 与变量的关系
1)block 与局部变量
int temp = 100;
void (^myBlock)(void) = ^(void) {
NSLog(@"%i", temp++);
NSLog(@"%i", temp + 1);
};
编写完上述代码编译器就会对第一个 NSLog 报错,说明在 block 对象的匿名函数中是不能修改局部变量的值的;而第二个不会报错,说明在 block 对象的匿名函数中是可以使用局部变量的那要是必须在匿名函数中修改局部变量时该怎么办??可以用 __bolck 关键字修饰所要修改的变量,即
__block int temp = 100;
void (^myBlock)(void) = ^(void) {
NSLog(@"%i", temp++);
NSLog(@"%i", temp + 1);
};
此时,编译器就不会报错,且打印出 100 和 1022)block 与全局变量
int temp_2 = 100;
int main(int argc, const char * argv[]) {
@autoreleasepool {
// block 与全局变量
void (^myBlokc_2)(void) = ^(void) {
NSLog(@"%i", temp_2++);
NSLog(@"%i", temp_2 + 1);
};
}
return 0;
}
此时,编译器不会报错,且打印出100 和 102;也就是说,在 block 的匿名函数中是可以修改全局变量的