- block本质上也是一个OC对象,它内部也有个isa指针
- block是封装了函数调用以及函数调用环境的OC对象
- block是封装函数及其上下文的OC对象
查看block源码:
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
// 构造函数(类似于OC的init方法),返回结构体对象
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
// 封装了block执行逻辑的函数
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_c60393_mi_0);
}
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)};
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
// 定义block变量
void (*block)(void) = &__main_block_impl_0(
__main_block_func_0,
&__main_block_desc_0_DATA
);
// 执行block内部的代码
block->FuncPtr(block);
}
return 0;
}
第二部分:Block特点自动捕获变量
1
int a=10;
void (^Block)(void) = ^{
NSLog(@"a:%d",a);
};
a = 20;
Block();
输出值为 a:10
原因:创建block的时候,已经把a的值存储在里面了。
2
auto int a = 10;
static int b = 25;
void (^Block)(void) = ^{
NSLog(@"a:%d,num:%d",a,b);
};
a = 20;
b = 11;
Block();
输出结果为:a:10,b:11
愿意:auto变量block访问方式是值传递,static变量block访问方式是指针传递
clang编译以后的源码如下
int a = __cself->a; // bound by copy
int *b = __cself->b; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_d2875b_mi_0, a, (*b));
int a = 10;
static int b = 25;
block = ((void (*)())&__test_block_impl_0((void *)__test_block_func_0, &__test_block_desc_0_DATA, a, &b));
a = 20;
b = 11;
上述代码可查看 static修饰的变量,是根据指针访问的
第三部分 Block类型
block的类型,取决于isa指针,可以通过调用class方法或者isa指针查看具体类型,最终都是继承自NSBlock类型
- __NSGlobalBlock __ ( _NSConcreteGlobalBlock 0x1)
- __NSStackBlock __ ( _NSConcreteStackBlock 0x7 )
- __NSMallocBlock __ ( _NSConcreteMallocBlock 0x6)
指针在0x1是全局 0x6堆 0x7栈
int a = 1;
void (^block1)(void) = ^{
NSLog(@"block1");
};
block1();
void (^block2)(void) = ^{
NSLog(@"block2:%d",a);
};
block2();
NSLog(@"%@/%@/%@",block1,block2,[^{
NSLog(@"block3:%d",a);
} class]);
输出结果:
<NSGlobalBlock 0x1887898789899>/<NSMallocBlock 0x697878979>/<NSStackBlock 0x7s87687686>