Block可表示为 " 带有自动变量值的匿名函数 "
1. 为什么是匿名函数
在C语言中, 函数必须要有函数名, 如
void funcName(int a) {
printf("%d\n", a);
}
由上面的代码可见, 不知道函数名就无法调用函数.
但是Block就不一样, 不需要函数名
^ (int a) {
printf("%d\n", a);
}
2. 为什么叫做 " 带有自动变量值 "
2.1" 带有自动变量值 "
在Block中表现为 " 截获自动变量值 "
看个例子
int a = 10;
void (^blk)() = ^ {
printf("%d\n",a);
};
a ++;
blk();
输出结果: 10
这里截取到的是值
原因:上面代码中的这个可见a
作为参数,block中会重新创建一个自己的变量a
,这个变量a
是被赋予可见a
的值,但已经与可见a
没有关系;因此,可见a
改变,block中的变量a
不会改变
2.2 static关键字
如果我们在上一段代码中的int a = 10;
前面加上static
关键字,那会发生什么
#include <stdio.h>
int main() {
static int a = 10;
void (^blk)() = ^ {
printf("%d",a);
};
a++;
blk();
}
输出结果是: 11
这里截取到的是指针
原因:这里使用的是指针,block也会创建一个自己的指针变量a
来接受可见静态a
的指针,由于是指针,直接指向可见静态a
的内存地址,所以可见静态a
的改变是会影响到block截取的值的
2.3 __block关键字
说到Block外的变量问题, 不得不说说__block
关键字, 要想在Block中重新对Block外的变量赋值, 必须要在Block外的变量前加上__block
, 这是为什么呢? 我们看个例子
int main() {
__block int a = 10;
void (^blk)() = ^ {
printf("%d\n",a);
};
a ++;
blk();
}
输出结果是: 11
__block
更加复杂一些,__block会使a形成一个结构体,但本质就是指针
2.3 截获Objective-C对象
以NSMutableArray为例
NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1", @"2", nil];
void (^blk)(void) = ^ {
[arr insertObject:@"3" atIndex:2];
};
blk();
这样是可以的, 只是对可变数组进行修改, 而不是重新赋值
下面我们看一下对Objective-c对象重新赋值
报错, 加上
__block
关键字后即可正常使用
这里截取到的是值
原因:也是因为数组名就是指针,这里就是把指针作为参数;所以修改指针所指的内容是可以的,但是如果要重新赋值指针,是不允许的
我这里说的比较简单,具体的请查看“Objective-C高级编程”这本书