您的位置:首页 > 移动开发 > Objective-C

block的实现原理

2015-06-30 18:01 567 查看
block的实现原理

将代码在Xcode中编写后,编译查看结果,test3和test4的结果我想大家都能猜到,基本C语言的一致.

但test1和test2的实现原理是比较重要的,运行后对结果的怎么实现的无法理解.

代码如下:

void test1() {
int a = 8;
void (^myBlock)() = ^{
NSLog(@"a = %d",a);
};
a = 12;
myBlock();
}

void test2() {
__block int a = 8;
void (^myBlock)() = ^{
NSLog(@"a = %d",a);
};
a = 12;
myBlock();
}

void test3() {
static int a = 8;
void (^myBlock)() = ^{
NSLog(@"a = %d",a);
};
a = 12;
myBlock();
}

int a = 8;
void test4() {

void (^myBlock)() = ^{
NSLog(@"a = %d",a);
};
a = 12;
myBlock();
}

int main(int argc, const char * argv[]) {
test4();
return 0;
}
想要理解block的内部实现原理,我们需要将代码编译成cpp文件.在terminal中以clang -rewrite-objc main.m 指令将其编译生成 main.cpp文件,以下代码是截取重要部分的内容.
--------------------------------------------------------------------------    美丽的分割线  cpp分析部分 ---------------------------------------------------------------

//main函数

int main(int argc, const char * argv[]) {
test1();
return 0;
}
//block的实现部分

//1.从这里开始

重点:

//1.1.a的值被初始化成8

//1.2.被传入myBlock的是a,因此被传入的是a的值8.

//1.3由于传入的是8常量,因此在block中不能给a重新赋值.

//1.4block中传入3个参数,

//1.5注意此时a的值8已传入block中,此时可以理解为:block实现部分已经就绪,只欠西北风了</span>

//1.6重新给a赋值12,这个结赋值不会影响block中的a的值,因为block的参数已经传入了,更新后不会再传入

//1.7执行block代码

void test1() {
//1.1
int a = 8;
//1.2
//1.3
//1.4
//1.5
void (*myBlock)() = (void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA, a);
//1.6
a = 12;
//1.7
((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
}

//2.原先a的值以形参_a的形式传进来,并赋给a,因此block中的a的值为8

    /**

     *  __test1_block_impl_0的实现部分

     *

     *  @param fp       函数指针

     *  @param desc  结构体__test1_block_impl_0的字节长度

     *  @param _a     形参a

     *  @param flags 忽视它

     *

     */

struct __test1_block_impl_0 {
struct __block_impl impl;
struct __test1_block_desc_0* Desc;
int a;

__test1_block_impl_0(void *fp, struct __test1_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
/**

 *  block函数内部功能

 *

 *  @param __cself 结构体的内部变量的引用

 */

//将__test1_block_impl_0中的a的值传给局部变量a中,将会打印该a的值.

static void __test1_block_func_0(struct __test1_block_impl_0 *__cself) {
int a = __cself->a; // bound by copy

NSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_0,a);
}

//内部两个参数,第一个为保留,第二个为block的字节长度,通过sizeof(struct __test1_block_impl_0)得到值
static struct __test1_block_desc_0 {
size_t reserved;
size_t Block_size;
} __test1_block_desc_0_DATA = { 0, sizeof(struct __test1_block_impl_0)};

//这是block的结构,是个结构体,记住block是个结构体
struct __Block_byref_a_0 {
void *__isa;
__Block_byref_a_0 *__forwarding;
int __flags;
int __size;
int a;
};
--------------------------------------------------------------------------    美丽的分割线   test2分析---------------------------------------------------------------

//================ test2 =================================================================
struct __test2_block_impl_0 {
struct __block_impl impl;
struct __test2_block_desc_0* Desc;
__Block_byref_a_0 *a; // by ref
__test2_block_impl_0(void *fp, struct __test2_block_desc_0 *desc, __Block_byref_a_0 *_a, int flags=0) : a(_a->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __test2_block_func_0(struct __test2_block_impl_0 *__cself) {
__Block_byref_a_0 *a = __cself->a; // bound by ref

NSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_1,(a->__forwarding->a));
}
static void __test2_block_copy_0(struct __test2_block_impl_0*dst, struct __test2_block_impl_0*src) {_Block_object_assign((void*)&dst->a, (void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __test2_block_dispose_0(struct __test2_block_impl_0*src) {_Block_object_dispose((void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);}

static struct __test2_block_desc_0 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __test2_block_impl_0*, struct __test2_block_impl_0*);
void (*dispose)(struct __test2_block_impl_0*);
} __test2_block_desc_0_DATA = { 0, sizeof(struct __test2_block_impl_0), __test2_block_copy_0, __test2_block_dispose_0};

void test2() {
__attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 8};
}

/**

  *  test2与test1的区别在于此,将block中传入的不是a的值,而是a的地址

  *

  *  @param myBlock 函数名

  *  因此在block中可以重新对a进行赋值

  */

void (*myBlock)() = (void (*)())&__test2_block_impl_0((void *)__test2_block_func_0, &__test2_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344);
(a.__forwarding->a) = 12;
((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
}

只分析了test1和test2,我想test3和test4比较好理解.
--------------------------------------------------------------------------    美丽的分割线   test3和test4 cpp代码,自行分析---------------------------------------------------------------

/================ test3 =================================================================
struct __test3_block_impl_0 {
struct __block_impl impl;
struct __test3_block_desc_0* Desc;
int *a;
__test3_block_impl_0(void *fp, struct __test3_block_desc_0 *desc, int *_a, int flags=0) : a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __test3_block_func_0(struct __test3_block_impl_0 *__cself) {
int *a = __cself->a; // bound by copy

NSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_2,(*a));
}

static struct __test3_block_desc_0 {
size_t reserved;
size_t Block_size;
} __test3_block_desc_0_DATA = { 0, sizeof(struct __test3_block_impl_0)};
void test3() {
static int a = 8;
void (*myBlock)() = (void (*)())&__test3_block_impl_0((void *)__test3_block_func_0, &__test3_block_desc_0_DATA, &a);
a = 12;
((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
}

//================ test4 =================================================================
int a = 8;
struct __test4_block_impl_0 {
struct __block_impl impl;
struct __test4_block_desc_0* Desc;
__test4_block_impl_0(void *fp, struct __test4_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __test4_block_func_0(struct __test4_block_impl_0 *__cself) {

NSLog((NSString *)&__NSConstantStringImpl__var_folders_16_2nnq6r3n5sq_4ynmhpf31szm0000gp_T_main_d05376_mi_3,a);
}

static struct __test4_block_desc_0 {
size_t reserved;
size_t Block_size;
} __test4_block_desc_0_DATA = { 0, sizeof(struct __test4_block_impl_0)};
void test4() {

void (*myBlock)() = (void (*)())&__test4_block_impl_0((void *)__test4_block_func_0, &__test4_block_desc_0_DATA);
a = 12;
((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
}

test3是由static声明,test4是全局变量,因此内从中只有一份.

---end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息