- 什么是block
- 什么是block调用
- block截获变量
- __block修饰符用在什么场景,__block变量__forwarding指针的作用
- block的copy操作
- block的循环引用
1、Objc测试代码
@implementation Ablock
int a3 = 3;
static int a4 = 4;
- (void)test {
int a1 = 1;
static int a2 = 2;
__block int a5 = 5;
__strong NSString *a6 = @"66";
__unsafe_unretained NSString *a7 = @"77";
int (^someblock)(int b) = ^(int b){
a1;
a2;
a3;
a4;
a6;
a7;
a5 = 55;
return b+a1+a2+a3+a4+a5;
};
someblock(3);
}
@end
2、转化后的c++代码分析
使用clang可以转objc为c++代码
clang -rewrite-objc -fobjc-arc Ablock.m
当前目录下生成Ablock.cpp文件
原来的OC代码被编译转化成如下调用:
static void _I_Ablock_test(Ablock * self, SEL _cmd) {
int a1 = 1;
static int a2 = 2;
__attribute__((__blocks__(byref))) __Block_byref_a5_0 a5 = {(void*)0,(__Block_byref_a5_0 *)&a5, 0, sizeof(__Block_byref_a5_0), 5};
__attribute__((objc_ownership(strong))) NSString *a6 = (NSString *)&__NSConstantStringImpl__var_folders_4j_z1n6phgx4d11klg60p7d3b240000gn_T_Ablock_da6be4_mi_0;
__attribute__((objc_ownership(none))) NSString *a7 = (NSString *)&__NSConstantStringImpl__var_folders_4j_z1n6phgx4d11klg60p7d3b240000gn_T_Ablock_da6be4_mi_1;
// 什么是block
//block封装函数和上下文的对象
int (*someblock)(int b) = ((int (*)(int))&__Ablock__test_block_impl_0((void *)__Ablock__test_block_func_0, &__Ablock__test_block_desc_0_DATA, a1, &a2, a6, a7,
(__Block_byref_a5_0 *)&a5, 570425344));
// block调用
//调用block就是调用函数
// struct __Ablock__test_block_impl_0 类型强制转化为struct __block_impl 类型
((int (*)(__block_impl *, int))((__block_impl *)someblock)->FuncPtr)((__block_impl *)someblock, 3);
}
找到各类型定义如下:
struct __Block_byref_a5_0 { //__block转化为了结构体
void *__isa; //有isa ,__block变量也转化为了对象
__Block_byref_a5_0 *__forwarding; // __forwarding指针
int __flags;
int __size;
int a5; // block变量
};
struct __block_impl {
void *isa; //是对象。
int Flags;
int Reserved;
void *FuncPtr;//函数指针
};
void *_NSConcreteGlobalBlock[32]; //全局block
void *_NSConcreteStackBlock[32]; //栈block
_NSConcreteMallocBlock //堆block
struct __Ablock__test_block_impl_0 { //block对象
struct __block_impl impl; //block对象。struct __Ablock__test_block_impl_0 和 struct __block_impl可以强制地址类型转换,因为它是内存第一个空间位置,所以互相转也没啥都是指向同一个内存首地址
struct __Ablock__test_block_desc_0* Desc;
int a1;
int *a2;
NSString *__strong a6;
NSString *__unsafe_unretained a7;
__Block_byref_a5_0 *a5; // by ref
__Ablock__test_block_impl_0(void *fp, struct __Ablock__test_block_desc_0 *desc, int _a1, int *_a2, NSString *__strong _a6, NSString *__unsafe_unretained _a7, __Block_byref_a5_0 *_a5, int flags=0) : a1(_a1), a2(_a2), a6(_a6), a7(_a7), a5(_a5->__forwarding) {
impl.isa = &_NSConcreteStackBlock; //栈block
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
int a3 = 3; //全局变量 不截获
static int a4 = 4;//静态全局变量 不截获
// 这就是FuncPtr
static int __Ablock__test_block_func_0(struct __Ablock__test_block_impl_0 *__cself, int b) {
__Block_byref_a5_0 *a5 = __cself->a5; // bound by ref __block转换为对象,内部有__forwarding指针指向block变量。如果是 struct __block_impl 是栈类型block,__forwarding指向__block变量自己,如果是堆上,则指向堆上__block变量
int a1 = __cself->a1; // bound by copy 基本数据类型,截获其值
int *a2 = __cself->a2; // bound by copy。 静态局部变量, 截获指针
NSString *__strong a6 = __cself->a6; // bound by copy 对象类型, 连同所属权修饰符一起截获
NSString *__unsafe_unretained a7 = __cself->a7; // bound by copy 对象类型, 连同所属权修饰符一起截获
a1;
(*a2);
a3;
a4;
a6;
a7;
(a5->__forwarding->a5) = 55;
return b+a1+(*a2)+a3+a4+(a5->__forwarding->a5);
}
static void __Ablock__test_block_copy_0(struct __Ablock__test_block_impl_0*dst, struct __Ablock__test_block_impl_0*src) {_Block_object_assign((void*)&dst->a6, (void*)src->a6, 3/*BLOCK_FIELD_IS_OBJECT*/);_Block_object_assign((void*)&dst->a7, (void*)src->a7, 3/*BLOCK_FIELD_IS_OBJECT*/);_Block_object_assign((void*)&dst->a5, (void*)src->a5, 8/*BLOCK_FIELD_IS_BYREF*/);}
static void __Ablock__test_block_dispose_0(struct __Ablock__test_block_impl_0*src) {_Block_object_dispose((void*)src->a6, 3/*BLOCK_FIELD_IS_OBJECT*/);_Block_object_dispose((void*)src->a7, 3/*BLOCK_FIELD_IS_OBJECT*/);_Block_object_dispose((void*)src->a5, 8/*BLOCK_FIELD_IS_BYREF*/);}
static struct __Ablock__test_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __Ablock__test_block_impl_0*, struct __Ablock__test_block_impl_0*);
void (*dispose)(struct __Ablock__test_block_impl_0*);
} __Ablock__test_block_desc_0_DATA = { 0, sizeof(struct __Ablock__test_block_impl_0), __Ablock__test_block_copy_0, __Ablock__test_block_dispose_0};
网友评论