Resumen sustancial de aprendizaje de bloques

Actualizar registros

Tiempo Revisión
12 de abril de 2020 Primer borrador

Prólogo

  • En la actualidad, los blogs de Blocks buscados en Internet se basan generalmente en el libro clásico "Objective-C Advanced Programming iOS and OS X Multithreading and Memory Management".
  • Este artículo es similar, y agregaré mi propio resumen y pensaré tanto como sea posible.

La esencia de los bloques

Convertir código Objective-C a código C / C ++

  • nombre de archivo de código fuente clang -rewrite-objc

Declaración de bloque simple

int main(int argc, const char * argv[]) {
    void (^blk)(void) = ^{
        printf("Block\n");
    };
    blk();
    return 0;
}

El código C / C ++ convertido

//block的实现
struct __block_impl {
  //由于第一个成员变量是isa指针,其实是一个OC对象。本对象中记录了block函数对应的函数指针

  void *isa;        //block isa指针,指向类对象(stack、malloc、global三种类型之一)
  int Flags;        //某些标志,暂不深入研究
  int Reserved;     //保留区域,以后版本升级可能会用到
  void *FuncPtr;    //函数指针
};

//这就是block本身对应的结构
struct __main_block_impl_0 {
  //只有两个成员变量。其中impl是一个OC对象

  struct __block_impl impl;
  struct __main_block_desc_0* Desc;     //该block的描述
  
  //block如果捕获了一些变量,则会添加到这里
  
  //C++中可以往struct中增加构造函数
  __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;
  }
};

//静态全局函数, 函数参数就是__main_block_impl_0本身的指针。和C++和OC中调用对象成员函数类似,第一参数都是this(self)
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
     printf("Block\n");
}

//静态全局结构体
static struct __main_block_desc_0 {
  size_t reserved;          //保留区域,以后版本升级可能会用到
  size_t Block_size;        //本block大小
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};

int main(int argc, const char * argv[]) {
    //由于括号嵌套较多,我这里采取特殊的换行和空格格式,旨在看清楚括号嵌套背后的实际语法。


    //block表达式转换
    void (*blk)(void) = (
    (void (*)())                            //强制转换成 void (*)(void) 类型的函数指针
    &                                       //取地址,记录该栈对象的地址
    __main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA)     //调用struct构造函数生成该block结构体实例
    
    );
    
    //上述的blk的类型暂时转换成了 void (*)(void),但其实它应该是一个 struct __main_block_impl_0* 类型
    //由于下列的调用中还要对其进行强制转换,所以上述转成什么类型,其实无关紧要。只要把该指针记录下来就行。
    
    //block调用
    (   
        (void (*)(__block_impl *))      //将函数指针强制转换成 void (*)(__block_impl *) 类型的函数指针
        ((__block_impl *)blk)->FuncPtr  //先将 blk 强制转成 __block_impl* 类型,再取其成员变量FuncPtr。则得到一个 void * 类型的变量
    )
    ((__block_impl *)blk)   //调用参数,即将 blk 强制转成 __block_impl* 类型
    ;              
    return 0;
}
  • He insertado comentarios detallados relevantes en el código fuente anterior, y eliminé el efecto de anidar paréntesis por líneas nuevas y espacios.

  • Hay un punto de conocimiento de que el puntero se ve obligado a girar y se necesita ciencia. (Acerca de la transferencia forzada del tipo blk en la función principal)

  • Presta atención a las reglas de nomenclatura de la estructura.

    • El autor de "OC Advanced Programming" dijo: El nombre de la función a la que pertenece la gramática de bloque (principal aquí) y el valor de orden de la gramática de bloque que aparece en la función (aquí 0) para nombrar la función transformada por el sonido metálico.

Resumen

  • El bloque declarado por el programador, el compilador generará el objeto Objective-C correspondiente (esencialmente una estructura, debido al puntero isa, que coincide con la definición del objeto Objective-C, por lo que es un objeto Objective-C).
  • Este tipo de objeto registra el puntero de función correspondiente al bloque y almacena las variables capturadas por el bloque. Por lo tanto, cuando se llama posteriormente al bloque, se llama realmente al puntero de función registrado por el objeto Objective-C, y se pasan los parámetros (el puntero del propio objeto de bloque, la variable capturada por el bloque).

Referencias

Supongo que te gusta

Origin www.cnblogs.com/HelloGreen/p/12684721.html
Recomendado
Clasificación