Block __block修饰符

如果block需要捕获某个变量后进行赋值,这个变量在声明时需要使用 __block修饰。

void testBlock2() {
    
    __block int num = 3;
    void(^block)(int) = ^(int i){
        num = 4;
        NSLog(@"i * num = %d", num * i);
    };
    num = 5;
    block(2); 
}

clang -rewrite-objc main.m,查看main.cpp文件

void testBlock2() {

    __attribute__((__blocks__(byref))) __Block_byref_num_0 num = 
                        {(void*)0,(__Block_byref_num_0 *)&num, 0, sizeof(__Block_byref_num_0), 3};
    void(*block)(int) = ((void (*)(int))&__testBlock2_block_impl_0((void *)__testBlock2_block_func_0, 
                        &__testBlock2_block_desc_0_DATA, (__Block_byref_num_0 *)&num, 570425344));
    (num.__forwarding->num) = 5;
    ((void (*)(__block_impl *, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, 2);
}

__block修饰的局部变量基本类型变成了 __Block_byref_num_0 结构体

struct __Block_byref_num_0 {
  void *__isa;
__Block_byref_num_0 *__forwarding;
 int __flags;
 int __size;
 int num;
};

struct __testBlock2_block_impl_0 {
  struct __block_impl impl;
  struct __testBlock2_block_desc_0* Desc;
  __Block_byref_num_0 *num; // by ref
  __testBlock2_block_impl_0(void *fp, struct __testBlock2_block_desc_0 *desc, 
                            __Block_byref_num_0 *_num, int flags=0) : num(_num->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

此时 _num->__forwarding 指向 __Block_byref_num_0 *num。
(num.__forwarding->num) = 5 这是再给num对象的num属性赋值。
__block修饰后,局部变量会被转化一个对象,局部变量的值将会是这个对象一个成员变量,而截获的是这个对象。
与没有__block修饰区分开,没有__block修饰时,是截获的值。

void testBlock2() {
    
    __block int num = 3;
    void(^block)(int) = ^(int i){
        NSLog(@"i * num = %d", num * i);
    };
    num = 5;
    block(2); // i * num = 10
}

void testBlock3() {
    
    int num = 3;
    void(^block)(int) = ^(int i){
        NSLog(@"i * num = %d", num * i);
    };
    num = 5;
    block(2); // i * num = 6
}

如果截获的变量,不赋值,仅仅是使用,不需要使用__block

void testBlock4() {
    
    //不需要__block修饰,没有对array赋值,而仅仅是使用。
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
    void(^block)(int) = ^(int i){
        [array addObject:@(i)];
    };
    block(2);
}

你可能感兴趣的:(Block __block修饰符)