iOS technical articles: from use to understand the underlying principles of the block (II)

block essence

Preface

Last article primarily through a simple demo shows the block usage scenario herein, this article will be based on iOS technical articles: from use to understand the underlying principles of the block (a) to learn more about the underlying implementation principle block.

block as an "anonymous functions with automatic variable values", in an actual compile time, we can not be converted into the source code we can understand, but clang (LLVM compiler) having a readable source code into our functions. The following command line input terminal, available .cpp file.

    clang -rewrite-objc 源代码文件名

In main.m implemented as follows

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        void(^myBlock)(void)=^{
            NSLog(@"testtest");
        };
        myBlock();
    }
    return 0;
}

By clang we get to the main.cpp file, open the file we can see about 10w lines of code, of course, we do not start to finish careful analysis of each block. We only need to look at the last few lines of analysis can then step by step.

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        void(*myBlock)(void)=((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
        ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
    }
    return 0;
}

In the main function entry Here we can see that we achieve the original block is converted to another mode display. Do not worry you do not see from here a step by step analysis.

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

We can see the internal structure __main_block_impl_0 by global search is:

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;
  }
};

This contains two structures block_impl and main_block_desc_0,

struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};

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

//__main_block_impl_0 结构声明
__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;
  }

It is easy to see: 1.main_block_impl_0 is a C ++ implementation of the block, is the main _0 represents the first of several in the block, which contains the retention reserved and size Block_size. 2.block_impl is the internal block implementation. Isa contains pointers, flags Flag, reserved retention and funcPtr defined types (ps: _NSConcreteStackBlock class_t equivalent structure examples may want to know you understand under).

From here we can see main_block_impl_0 is probably pass two values ​​main_block_func_0 and & main_block_desc_0_DATA. Func is a structure, and the other is desc pointer. These are the initialization main_block_impl_0 structure member of the source code. Next, we see that the original is not easy to understand the above analysis can be __main_block_impl_0

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

change into:

    struct __main_block_impl_0 tmp = __main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA);
    struct __main_block_impl_0*myBlock = &tmp;

This is easy to understand, the source code main_block_impl_0 structure type automatic variable, i.e., generated on the stack structure main_block_impl_0 instance pointer assigned to __main_block_impl_0 structure pointer type variable myBlock. The
myBlock();underlying implementation is as follows:

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

After the conversion is

(*myBlock->impl.FuncPtr)(myBlock);

This is a simple function pointer call the function.

Can be understood as: __main_block_func_0 function block has a pointer syntax conversion is assigned in the member variable FuncPtr.

 

This will understand the essence of the block.

Guess you like

Origin www.cnblogs.com/lovemargin/p/11945320.html