傻瓜学编程之block_2

Posted 肖无情

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了傻瓜学编程之block_2相关的知识,希望对你有一定的参考价值。

block的实质

以一个简单的实现为列子;

- (void)myBlcokTest{
    void (^blk)()=^{
        printf(@“beijinghuanyingni”);
    };
    blk();
}
    

 终端:clang -rewrite-objc 类文件名.m

cpp文件中关键代码:

    static void _I_People_myBlcokTest(People * self, SEL _cmd) {
        void (*blk)()=((void (*)())&__People__myBlcokTest_block_impl_0((void *)__People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA));
        ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);

    }
    

    
    static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
        printf("woshinidexiaodaye");
    }
    

    struct __People__myBlcokTest_block_impl_0 {  
        struct __block_impl impl;
        struct __People__myBlcokTest_block_desc_0* Desc;
        __People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0) {
            impl.isa = &_NSConcreteStackBlock;
            impl.Flags = flags;
            impl.FuncPtr = fp;
            Desc = desc;
        }
    };
    
//    第一个成员
    struct __block_impl {
        void *isa;
        int Flags;
        int Reserved;
        void *FuncPtr;
    };
//    第二个成员
    static struct __People__myBlcokTest_block_desc_0 {
        size_t reserved;// 升级版本所需要的区域
        size_t Block_size;//block大小
    } __People__myBlcokTest_block_desc_0_DATA = { 0, sizeof(struct __People__myBlcokTest_block_impl_0)};  

 

运行时的myBlcokTest方法;

 static void _I_People_myBlcokTest(People * self, SEL _cmd) {
        
        void (*blk)()=((void (*)())&__People__myBlcokTest_block_impl_0((void *)__People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA));
        
        ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);

 }

去掉类型转化

 

static void _I_People_myBlcokTest(People * self, SEL _cmd) {
        __People__myBlcokTest_block_impl_0 blk = __People__myBlcokTest_block_impl_0( __People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA));
        
      、、、
    }

__People__myBlcokTest_block_impl_0:是一个结构体 包含两个成员:

struct __block_impl impl;
struct __People__myBlcokTest_block_desc_0* Desc;

以及一个构造函数:
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0) 

 

struct __People__myBlcokTest_block_impl_0 {  
    成员一:    struct __block_impl impl;   // __block_impl结构体
                  struct __block_impl {
                             void *isa;
                             int Flags;
                             int Reserved;
                             void *FuncPtr;
                    };
     成员二:     struct __People__myBlcokTest_block_desc_0* Desc;//__People__myBlcokTest_block_desc_0结构体

                        static struct __People__myBlcokTest_block_desc_0 {
                              size_t reserved;// 升级版本所需要的区域
                               size_t Block_size;//block大小
                         } 



  构造函数:
          构造函数中成员的处理 在后面 构造函数中参数的处理部分解释;
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
{
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};

 

通过结构体的构造函数生成一个block实例

 __People__myBlcokTest_block_impl_0 blk = __People__myBlcokTest_block_impl_0( __People__myBlcokTest_block_func_0,
&__People__myBlcokTest_block_desc_0_DATA));

 构造函数参数的意义:
参数一:    __People__myBlcokTest_block_func_0  //函数实现地址  在把函数赋值给函数指针的时候可以省略&;
在构造函数参数的意义: 把函数的地址赋值给指针 void *fp
函数的具体实现代码:
static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
        printf("woshinidexiaodaye");
    }
这里面的__cself是什么后面会解释;
参数二: &__People__myBlcokTest_block_desc_0_DATA // __People__myBlcokTest_block_desc_0的默认初始化
{ 0, sizeof(struct __People__myBlcokTest_block_impl_0) //使用__People__myBlcokTest_block_impl_0的大小进行初始化

具体代码:
static struct __People__myBlcokTest_block_desc_0 { size_t reserved;// 升级版本所需要的区域 size_t Block_size;//block大小 } __People__myBlcokTest_block_desc_0_DATA = { 0, sizeof(struct __People__myBlcokTest_block_impl_0)};

 

 函数指针 与指针函数点击这里

构造函数中参数的处理

 __People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
           { 
                impl.isa = &_NSConcreteStackBlock;
                impl.Flags = flags;
                impl.FuncPtr = fp;
                Desc = desc;
            } 
赋值之后:
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
           { 
                impl.isa = &_NSConcreteStackBlock;//_NSConcreteStackBlock用于初始化isa成员  后面具体解释
                impl.Flags = 0;
                impl.FuncPtr =__People__myBlcokTest_block_func_0;
imlp.Reserved=0;
                Desc =__People__myBlcokTest_block_desc_0_DATA;
            }

  再来看看block的调用:  

     blk();

((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);

 简化

 ((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); =>(blk ->FuncPtr)(blk)

 获取blk结构体中函数指针FuncPtr 通过该函数指针调用函数 并且参数值为blk   点击这里

 

这个等价于

(blk ->FuncPtr)(blk) 相当于

   blk -> __People__myBlcokTest_block_func_0(blk);

再看看

static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
        printf("woshinidexiaodaye");
    }

说明 __cself 就是blk 本身

以上是关于傻瓜学编程之block_2的主要内容,如果未能解决你的问题,请参考以下文章

傻瓜学编程之block_1

iOS学习之代码块(Block)

PAT乙级题库“傻瓜”题解之跟奥巴马一起编程

Vue之项目结构傻瓜式

面向面试编程代码片段之GC

Objective-C基础之_ weak, _ strong , __ block