【Objective-C高级编程】iOS与OS X多线程和内存管理(四) Block的实现

使用clang 的编译选项查看blocks 

“clang -rewrite-objc 源代码文件名”

源代码:
int main ()
{
     void (^blk)(void) = ^{ printf(“Block”); };
     blk ();
     return 0;
}



转换为:
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;
    
    __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;
    }
};

static void __main_block_func_0 (struct __main_block_impl_0 *__cself) {
    printf("Block");
}

static struct __main_block_desc_0 {
    unsigned long reserved;
    unsigned long Block_size;
} __main_block_desc_0_DATA = {
    0,
    sizeof(struct __main_block_impl_0)
};

int main()
{
    void (*blk)(void) = (void (*)(void)) & __main_block_impl_0( (void *)__main_block_func_0, &__main_block_desc_0_DATA);
    
    ((void (*)(struct __block_impl *))( (struct __block_impl *)blk)-> FuncPtr)((struct __block_impl *)blk);
    
    return 0;
}



以上代码解析:

void (*blk)(void) = (void (*)(void)) & __main_block_impl_0( (void *)__main_block_func_0, &__main_block_desc_0_DATA);


转换太多,进行简化:
struct __main_block_impl_0 tmp = __main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA);
struct __main_block_impl_0 *blk = &tmp;


而 ((void (*)(struct __block_impl *))( (struct __block_impl *)blk)-> FuncPtr)((struct __block_impl *)blk);
则可以简化为:
(*blk—>impl.FuncPtr)(blk);
实际上就是 函数指针调用 函数。



typedef strcut objc_object {
     Class isa;
} *id;





typedef strict objc_class *Class;





struct objc_class {
     Class isa;
};




各类的结构体就是基于objc_class 结构体的class_t 结构体。
struct class_t {
     struct class_t *isa;
     struct class_t *superclass;
     Cache cache;
     IMP *vtable;
     uintptr_t data_NEVER_USE;
};



总的来说,所谓“截获自动变量值”意味着在执行Block语法时,Block语法表达式所使用的自动变量值被保存到Block的结构体实例(Block自身)中。

当我们视图改变Block中的自动变量值时会出现编译错误。
解决的方法有两种:
①使用静态变量。Block 会保存静态变量的的指针对其进行访问。 将静态变量的指针传递给__main_block_impl_0 结构体的构造函数并保存。 但是我们并没有保存自动变量的指针。这是因为超出自动变量的作用域的时候,自动变量被废弃,通过指针来访问会产生不可预料的错误。但静态变量则不会。

②使用__block 存储域类说明符。
C语言有以下存储域类说明符: typedef , extern, static, auto, register.





















你可能感兴趣的:(读书笔记)