天天看点

Block 的原理

1.Block的本质是一个结构体指针, 回调原理: 通过当前的block对应的结构体指针找到对应的结构体,然后在结构体中找到对应的函数名称, 最后调用函数 . 2.通过__block \ static \ 全局变量 修饰或定义的变量,传入到 block 对应的结构体中实质时传入了对应的变量地址& a, 所以修改变量后block 内部的变量也随着响应的改变.  3.局部静态变量则传入的是实际的值, 所以即便修改原来的变量 block 内部的值仍不会变化. EG: ObjC 代码: #import <Foundation/Foundation.h>

// 局部变量

void test1(){

    int a = 10 ;

    void (^block)() = ^{

        NSLog( @"test1 a = %d" , a);

    };

    a = 20 ;

    block();

}

// 局部静态变量

void test2(){

  static   int a = 10 ;

    void (^block)() = ^{

        NSLog( @"test2 a = %d" , a);

    };

    a = 20 ;

    block();

}

//__block 修饰

void test3(){

    __block   int a = 10 ;

    void (^block)() = ^{

        NSLog( @"test3 a = %d" , a);

    };

    a = 20 ;

    block();

}

// 全局变量调用

int a = 30 ;

void test4(){

        a = 50 ;

        void (^block)() = ^{

            NSLog( @"test4 a = %d" , a);

        };

        a = 20 ;

        block();

}

int main( int argc, const char * argv[]) {

    @autoreleasepool {

        test1(); //10

        test2(); //20

        test3(); //20

        test4(); //20

    }

    return 0 ; } 编译过后的c++代码; struct __test1_block_impl_0 {   struct __block_impl impl;

  struct __test1_block_desc_0* Desc;

  int a;

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

  }

};

static void __test1_block_func_0( struct __test1_block_impl_0 *__cself) {

  int a = __cself->a; // bound by copy

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_0n_2blpmxd960zf5lxdfdrd9l9r0000gn_T_main_504a7b_mi_0, a);

    }

static struct __test1_block_desc_0 {

  size_t reserved;

  size_t Block_size;

} __test1_block_desc_0_DATA = { 0 , sizeof ( struct __test1_block_impl_0)};

void test1(){

    int a = 10 ;

    void (*block)() = (( void (*)())&__test1_block_impl_0(( void *)__test1_block_func_0, &__test1_block_desc_0_DATA, a));

    a = 20 ;

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

}

struct __test2_block_impl_0 {

  struct __block_impl impl;

  struct __test2_block_desc_0* Desc;

  int *a;

  __test2_block_impl_0( void *fp, struct __test2_block_desc_0 *desc, int *_a, int flags= 0 ) : a(_a) {

    impl.isa = &_NSConcreteStackBlock;

    impl.Flags = flags;

    impl.FuncPtr = fp;

    Desc = desc;

  }

};

static void __test2_block_func_0( struct __test2_block_impl_0 *__cself) {

  int *a = __cself->a; // bound by copy

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_0n_2blpmxd960zf5lxdfdrd9l9r0000gn_T_main_504a7b_mi_1, (*a));

    }

static struct __test2_block_desc_0 {

  size_t reserved;

  size_t Block_size;

} __test2_block_desc_0_DATA = { 0 , sizeof ( struct __test2_block_impl_0)};

void test2(){

  static int a = 10 ;

    void (*block)() = (( void (*)())&__test2_block_impl_0(( void *)__test2_block_func_0, &__test2_block_desc_0_DATA, &a));

    a = 20 ;

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

}

struct __Block_byref_a_0 {

  void *__isa;

__Block_byref_a_0 *__forwarding;

  int __flags;

  int __size;

  int a;

};

struct __test3_block_impl_0 {

  struct __block_impl impl;

  struct __test3_block_desc_0* Desc;

  __Block_byref_a_0 *a; // by ref

  __test3_block_impl_0( void *fp, struct __test3_block_desc_0 *desc, __Block_byref_a_0 *_a, int flags= 0 ) : a(_a->__forwarding) {

    impl.isa = &_NSConcreteStackBlock;

    impl.Flags = flags;

    impl.FuncPtr = fp;

    Desc = desc;

  }

};

static void __test3_block_func_0( struct __test3_block_impl_0 *__cself) {

  __Block_byref_a_0 *a = __cself->a; // bound by ref

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_0n_2blpmxd960zf5lxdfdrd9l9r0000gn_T_main_504a7b_mi_2, (a->__forwarding->a));

    }

static void __test3_block_copy_0( struct __test3_block_impl_0*dst, struct __test3_block_impl_0*src) {_Block_object_assign(( void *)&dst->a, ( void *)src->a, 8 );}

static void __test3_block_dispose_0( struct __test3_block_impl_0*src) {_Block_object_dispose(( void *)src->a, 8 );}

static struct __test3_block_desc_0 {

  size_t reserved;

  size_t Block_size;

  void (*copy)( struct __test3_block_impl_0*, struct __test3_block_impl_0*);

  void (*dispose)( struct __test3_block_impl_0*);

} __test3_block_desc_0_DATA = { 0 , sizeof ( struct __test3_block_impl_0), __test3_block_copy_0, __test3_block_dispose_0};

void test3(){     __attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *) &a , 0, sizeof(__Block_byref_a_0), 10};     void (*block)() = ((void (*)())&__test3_block_impl_0((void *)__test3_block_func_0, &__test3_block_desc_0_DATA, (__Block_byref_a_0 *) &a , 570425344));     (a.__forwarding->a) = 20 ;

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

}

int a = 30 ;

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) {

            NSLog((NSString *)&__NSConstantStringImpl__var_folders_0n_2blpmxd960zf5lxdfdrd9l9r0000gn_T_main_504a7b_mi_3, 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(){

        a = 50 ;

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

}

int main( int argc, const char * argv[]) {

    { __AtAutoreleasePool __autoreleasepool;

        test1();

        test2();

        test3();

        test4();

    }

    return 0 ; }