1.Block的本事是什么?
2.Block变量捕获
3.Block内存管理
4.Block的修饰符 __block
问题1:Block的本质是封装了函数以及函数上下文的对象。
int main(int argc, const char * argv[]) { @autoreleasepool { void(^printBlock)(void) = ^() {
NSLog(@"block print");
}; printBlock(); } return 0;}通过clang命令转换成cpp文件查看编译器把Block解析成什么
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
//1.先看这里
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
void(*printBlock)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)printBlock)->FuncPtr)((__block_impl *)printBlock);
}
return 0;
}
//2.看这个函数
struct __main_block_impl_0 {
struct __block_impl impl;//看下面__block_impl 实现里面有个isa
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;//这是Block内存stack一种
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
//3isa可以说明block本质上是oc的对象
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
//block 函数体
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_73_gxjqw_b94kz_9bcxk58jxb240000gn_T_main_38ac7a_mi_0);
}
//block 函数描述
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
Block变量捕获
//转换前的代码
//全局变量int global_var = 11;//静态全局变量static int static_global_var = 10;int main(int argc, const char * argv[]) { @autoreleasepool { //局部变量
int number = 10; //对象
__unsafe_unretained id obj = nil; //静态局部变量 static int multiplier = 20;void(^printBlock)(void) = ^() {
NSLog(@"multiplier=%d",multiplier);
NSLog(@"obj=%@",obj);
NSLog(@"number=%d",number);
NSLog(@"global_var = %d",global_var);
};
printBlock();
}
return 0;}
//转换后的代码
int global_var = 11;
static int static_global_var = 10;
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int *multiplier;
id obj;
int number;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_multiplier, id _obj, int _number, int flags=0) : multiplier(_multiplier), obj(_obj), number(_number) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
- 局部变量:值捕获
- 静态变量:指针捕获
- 全局变量:不捕获
看考题?
@autoreleasepool {
//局部变量
int number = 10;
//对象
__unsafe_unretained id obj = nil;
//静态局部变量
static int multiplier = 20;
void(^printBlock)(int a) = ^(int a) {
NSLog(@"multiplier=%d",multiplier);
NSLog(@"obj=%@",obj);
NSLog(@"number=%d",number * a);
NSLog(@"global_var = %d",global_var);
};
number = 9;
printBlock(3);//number打印30 还是27 }Block的修饰符
NSMutableArray *array = [NSMutableArray arrayWithCapacity:5];
void(^block)(void) = ^{
[array addObject:@"3333"];
NSLog(@"array:%@",array);
};
block();问打印什么会会不报异常呢? }
case2
__block NSMutableArray *array = nil;
void(^block)(void) = ^{
array = [NSMutableArray array];
[array addObject:@"333"];
NSLog(@"array:%@",array);
};
block();//打印什么
}
Block的内存分布
- 全局Block GloabalBlock
- 栈上Block StackBlock
- 堆上的Block MallocBlock
__block修饰符
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_array_0 *array; // by ref
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_array_0 *_array, int flags=0) : array(_array->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}