先了解 block 截获变量
-
基本数据类型
局部变量: 截获其值 -
对象类型
局部变量: 连同所有权修饰符一起截获 -
局部静态变量
: 指针形式截获 -
全局变量
: 不截获 -
静态全局变量
: 不截获
问题1: 看例子回答
int test1 = 2;
int(^Block)(int) = ^int(int n) {
return n * test1;
};
NSLog(@"result: %d", Block(6));
答案
12
block对于基本数据变量截获是截获其值 , 那么内部block截获基本数据类型2, 进行:
6 * 2 = 12
问题2: 看例子回答
- (void)blockTest1 {
int test1 = 2;
int(^Block)(int) = ^int(int n) {
return n * test1;
};
test1 = 3;
NSLog(@"result: %d", Block(6));
}
答案
12
相比问题1, block之后多加了一个对基本数据类型的赋值, 但是呢不要被迷惑了,
block对于基本数据变量截获是截获其 "值", 要深刻理解这句话. 简单来说, 再block之前基本数据类型是什么值, 直接写死在这个block里面, 不会变跟后面赋值个3没关系了, 可以理解成这样:
- (void)blockTest1 {
int test1 = 2;
int(^Block)(int) = ^int(int n) {
// 就是2 不会变
return n * 2;
};
test1 = 3;
NSLog(@"result: %d", Block(6));
}
那么 6 * 2 = 12
问题3: 看例子回答
- (void)blockTest1 {
static int test1 = 2;
int(^Block)(int) = ^int(int n) {
return n * test1;
};
test1 = 3;
NSLog(@"result: %d", Block(6));
}
答案
18
留意下这里 static int test1 = 2;
是局部静态变量, 局部静态变量block底层是以指针形式存放的, 后面有test1 = 3
, 指针指向3
那么 6 * 3 = 18
问题4: 看例子回答
static int test1 = 2;
- (void)blockTest1 {
int(^Block)(int) = ^int(int n) {
return n * test1;
};
test1 = 3;
NSLog(@"result: %d", Block(6));
}
答案
18
全局变量
和静态全局变量
block 不截获其内容, 通俗点说调用block时候, 当时变量是什么取什么值, 那么
6 * 3 = 18
问题5: 看例子回答打印结果
NSMutableArray *arr = [NSMutableArray array];
void(^Block)(void) = ^{
[arr addObject:@"123"];
};
[arr addObject:@"456"];
Block();
NSLog(@"%@", arr);
答案
[ 456, 123 ]
对象类型
局部变量是连同所有权修饰符一起截获, 这里其实block存放的是NSMutableArray *arr
指针, 后面数组先添加了"456", 指针对象指向是["456"], 再进行block操作, 即 ["456"]插入一个新元素"123", 结果 [ 456, 123 ]
问题6: 看例子回答打印结果
__block int test1 = 2;
int(^Block)(int) = ^int(int n) {
return n * test1;
};
test1 = 3;
NSLog(@"result: %d", Block(6));
答案
18
通俗讲, 其实__block
修饰数据型, 在底层已经变成对象 (实际上是一个结构体), 不是像通常基本数据类型一样存的那个值. 那么当后续 test1 有变化时候, 内部对象(结构体中__forwarding的指针)会指向新变化值, 即
3 * 8 = 18