__block的捕获

56 阅读1分钟
__block int a = 10;
NSLog(@"1: %p", &a);
dispatch_block_t block = ^{
    a = 20;
    NSLog(@"2: %p", &a);
};

NSLog(@"3: %p", &a);
block();
NSLog(@"4: %p", &a);

*********************运行结果*********************
**1: 0x7ff7b2544b48**
**3: 0x600003c997d8**
**2: 0x600003c997d8**
**4: 0x600003c997d8**

__block修饰的变量在Block完成初始化并捕获变量后会将所修饰的变量包装成一个新的对象,新的对象是__Block_byref_a_0,并且将__forwarding指针指向原有变量,Block在Copy之后__forwarding指针指向堆上的新变量。

struct __Block_byref_a_0 {
    void *__isa;    //(void*)0,
    struct __Block_byref_a_0 *__forwarding;    // &a
    int __flags;    //0
    int __size;    // sizeof(__Block_byref_a_0)
    int a;    // 10
}

在Block完成初始化并捕获变量后,在任意地方通过a访问的内存地址,都是__Block_byref_a_0的地址,这个对象被保存在堆上。