Block 详解

2017-07-20 Lyu.

纸上得来终觉浅,觉知此事要躬行。

block 相关内容已经看过很多很多的文章了,block 分为三种类型,block 需要用 copy 修饰等等。

block 可以转换成 C 代码来解析,其实本身是一个 struct 对象。

下面是自己通过代码的一点实践,源代码和转换到 C 之后的代码。

如何转换到 C++ 代码

通过 Xcode 建一个 command line tool 的工程,就是命令行项目,会自动生成一个** mian.m **文件。

在里面可以直接写 OC 的代码。

然后通过 Clang 进行装换

  • Clang 是一个编译器,支持 C语言、C++、Objective-C。

支持的指令如下


clang -fobjc-arc -framework Foundation hello.m -o hel

指令解释

  • -fobjc-arc表示编译需要支持ARC特性。
  • -framework Foundation表示引用Foundation框架,这个框架中定义了很多基本的类,例如字符串、数组、字典等等。
  • 后面的hello.m就是待编译的源代码文件名。
  • -o nihao表示输出的可执行文件的文件名是nihao。

我们这边是要把文件转成 C++

clang -rewrite-objc main.m

转换

下面就是转换前和转换之后的实例

block impl 的结构是这样

//block 的实现结构体
struct __block_impl {
    void *isa; //类型
    int Flags;// flags? 
    int Reserved; // ?
    void *FuncPtr; // 对应的函数
};

普通的 block


void blockFunc1(){

    int num = 100;

    void (^block)() = ^{

        NSLog(@"num equal %d",num);

    };

    num = 200;

    block();

}

得到如下的代码,相应的解释放在了注释之中。

//block 的本体
struct __blockFunc1_block_impl_0 {
  struct __block_impl impl;
  struct __blockFunc1_block_desc_0* Desc;
  int num;
    
  __blockFunc1_block_impl_0(void *fp, struct __blockFunc1_block_desc_0 *desc, int _num, int flags=0) : num(_num) {
    //stack block 栈
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
    
};


//真正执行的函数
static void __blockFunc1_block_func_0(struct __blockFunc1_block_impl_0 *__cself) {
    //有一个cself的对象 获取中间的 num 变量
  int num = __cself->num; // bound by copy
    //执行 nslog 打印
  NSLog((NSString *)&__NSConstantStringImpl__var_folders_zt_5kb2m4l154xd646nkb_6y02w0000gn_T_main_e94473_mi_0,num);
}


//block data 描述字段
static struct __blockFunc1_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __blockFunc1_block_desc_0_DATA = { 0, sizeof(struct __blockFunc1_block_impl_0)};



void blockFunc1(){
    int num = 100;
    //结构体的构造
    void (*block)() = ((void (*)()) &__blockFunc1_block_impl_0(
                                                               (void *)__blockFunc1_block_func_0,
                                                               &__blockFunc1_block_desc_0_DATA,
                                                               num));
    
    num = 200;
    // block -> func ( block )
    ((void (*)(__block_impl *)) ((__block_impl *)block)->FuncPtr) ((__block_impl *)block);
    
}

获取了 __block 修饰的对象的 block

void blockFunc2(){
    __block int num = 100;
    void (^block)() = ^{
        NSLog(@"num equal %d",num);
    };
    num = 200;
    block();
}

对 num 进行了一个 wrap 成为了一个结构体

struct __Block_byref_num_0 {
  void *__isa; //给了 0
__Block_byref_num_0 *__forwarding; // 自己
 int __flags; // 0
 int __size; // size of
 int num; // 100
};

struct __blockFunc2_block_impl_0 {
  struct __block_impl impl;
  struct __blockFunc2_block_desc_0* Desc;
  __Block_byref_num_0 *num; //  num 的结构体
  __blockFunc2_block_impl_0(void *fp, struct __blockFunc2_block_desc_0 *desc, __Block_byref_num_0 *_num, int flags=0) : num(_num->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

//block 的 des 增加了 copy 和 dispose 方法

extern "C" void _Block_object_assign(void *, const void *, const int)
    __attribute__((availability(macosx,introduced=10.6)));



extern "C" void _Block_object_dispose(const void *, const int)
    __attribute__((availability(macosx,introduced=10.6)));


static void __blockFunc2_block_copy_0(struct __blockFunc2_block_impl_0*dst, struct __blockFunc2_block_impl_0*src) {_Block_object_assign((void*)&dst->num, (void*)src->num, 8/*BLOCK_FIELD_IS_BYREF*/);}


static void __blockFunc2_block_dispose_0(struct __blockFunc2_block_impl_0*src) {_Block_object_dispose((void*)src->num, 8/*BLOCK_FIELD_IS_BYREF*/);}

// 这个 block 能够 copy
static struct __blockFunc2_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __blockFunc2_block_impl_0*, struct __blockFunc2_block_impl_0*);
  void (*dispose)(struct __blockFunc2_block_impl_0*);
} __blockFunc2_block_desc_0_DATA = { 0, sizeof(struct __blockFunc2_block_impl_0), __blockFunc2_block_copy_0, __blockFunc2_block_dispose_0};

用户评论
开源开发学习小组列表