ブロック問題

4847 ワード

開発ではblockをよく使いますが、まず簡単な基本的な使い方を見てみましょう.
void test1()
{
    int a = 10;
    void (^block)() = ^{
        NSLog(@"%d", a);
    };
    a = 20;
    block(); //      10
}
void test2()
{
    __block int a = 10;
    void (^block)() = ^{
        NSLog(@"%d", a);
    };
    a = 20;
    block(); //      20
}
void test3()
{
    static int a = 10;

    void (^block)() = ^{
        NSLog(@" %d", a);
    };
    a = 20;
    block(); //     20
}

// a         
int a = 10;
void test4()
{
    void (^block)() = ^{
        NSLog(@"a is %d", a);
    };
    a = 20;
    block();//     20
}
   main  

int main(int argc,const char * argv[]) {
    @autoreleasepool {
       
       test4();
        
  
    }
   return 0;
}
blockは実際には構造体を指すポインタであり、使用可能である.
clang -rewrite-objc  main.mはmain.mをmainに変換する.cppファイル
main関数でtest 1を呼び出し、main.mをmainに変換する.cpp後、cppファイルにtest 1関数が表示されます.
void test1()
{
    int a = 10;
   //_test1_block_impl_0     c++    ,              ,                C++           block    ,       __test1_block_func_0
 void (*block)() = ((void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA, a));  block  a       ,     block        10

    a = 20;
//3.     block                  FuncPtr

    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}
<pre name="code" class="cpp">struct __test1_block_impl_0 {
  struct __block_impl impl;
  struct __test1_block_desc_0* Desc;
  int a;
   // 2.__test1_block_impl_0        ,         FuncPtr
  __test1_block_impl_0(void *fp, struct __test1_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
block                  ,
static void __test1_block_func_0(struct __test1_block_impl_0 *__cself) {
  int a = __cself->a; // bound by copy

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_36_fw4zn5v15w10psb207f993_c0000gn_T_main_f13c04_mi_0, a);
    }

このことからblockに保存されているのは構造体を指すポインタであり,この構造体にはblock種のコードが入った関数が保存されていることがわかる.
 
  
 

在main.m中调用test2 转换为main.cpp文件后:

void test2()
{
    __attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 10};
   //     __test2_block_impl_0               a   ,   block    a      ,  block         
    void (*block)() = ((void (*)())&__test2_block_impl_0((void *)__test2_block_func_0, &__test2_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));

    (a.__forwarding->a) = 20;

    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}

同じ理屈だm
で呼び出すtest 3をmainに変換する.cppファイルの後:
void test3()
{
    static int a = 10;
    //     __test3_block_impl_0               a   ,   block    a      ,  block         >
    void (*block)() = ((void (*)())&__test3_block_impl_0((void *)__test3_block_func_0, &__test3_block_desc_0_DATA, &a));

    a = 20;

    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}

同じ理屈だmで呼び出すtest 4をmainに変換する.cppファイルの後:
int a = 10;//<span style="color:#ff0000;">    </span>

struct __test4_block_impl_0 {
  struct __block_impl impl;
  struct __test4_block_desc_0* Desc;
  __test4_block_impl_0(void *fp, struct __test4_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __test4_block_func_0(struct __test4_block_impl_0 *__cself) {
      //                    a  </span>
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_36_fw4zn5v15w10psb207f993_c0000gn_T_main_6730fe_mi_0, a);
    }

static struct __test4_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __test4_block_desc_0_DATA = { 0, sizeof(struct __test4_block_impl_0)};
void test4()
{
    void (*block)() = ((void (*)())&__test4_block_impl_0((void *)__test4_block_func_0, &__test4_block_desc_0_DATA));

    a = 20;

    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}