1、问:什么是Block?
Block是将函数及其执行上下文封装起来的对象
Block的调用,既是函数的调用
先来看下下面这段代码:
{
int multiplier = 6;
int (^Block)(int) = ^int (int num){
return num * multiplier;
};
Block(2);
}
可以使用 clang -rewrite-objc file.m
来查看block编译之后的文件内容
上面的代码经过转化以后变成了下面的代码
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int multiplier;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _multiplier, int flags=0) : multiplier(_multiplier) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
{
int multiplier = 6;
int (*Block)(int) = ((int (*)(int))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, multiplier));
((int (*)(__block_impl *, int))((__block_impl *)Block)->FuncPtr)((__block_impl *)Block, 2);
}
}
return 0;
}
2、什么是Block调用
block的调用就是函数的调用
3、截获变量
下面这道题是滴滴的真题
{
int multiplier = 6;
int (^Block)(int) = ^int (int num){
return num * multiplier;
};
multiplier = 4;
NSLog(@"result is %d",Block(2));
}
这道题的答案是:result is 12
block截获的变量分为不同的类型
如果在转化OC代码的时候用 clang -rewrite-objc -fobjc-arc file.m
来编译文件则跟上面不使用 -fobjc-arc
关键字编译的有所不同
其中连同所有权修饰符一起截获指的是:如果对象是用__unsafe_unretained和__strong修饰的,那么连这两个词也一块截获。
__unsafe_unretained id unsafe_obj;
__strong id strong_obj;
__block修饰符
一般情况下,对被截获变量进行赋值操作需添加 __block修饰符
赋值 != 使用
上面代码可以正常执行
array是局部变量,会被捕获进去,捕获进去的是NSMutableArray *array,array是指针变量,array本身不可以做修改,但是array指针指向的变量可以修改,也就是[array addobject:@123]没有问题
上面代码不可以执行
array = [NSMutableArray array];要修改的是指针变量array本身存储的内容,是不可以的。