理解iOS Block的_NSConcreteGlobalBlock类型

1,187 阅读2分钟

Block的定义

Block是将函数及其执行上下文封装的一个对象

Block的类型

  • __NSGlobalBlock__ ( _NSConcreteGlobalBlock )

  • __NSStackBlock__ ( _NSConcreteStackBlock )

  • __NSMallocBlock__ ( _NSConcreteMallocBlock )

其中三种不同的类型和环境对应如下

block类型环境
__NSGlobalBlock__没有访问auto变量
__NSStackBlock__访问了auto变量
__NSMallocBlock____NSStackBlock__调用了copy

其在内存中的分配如下对应

Block在内存上的位置的验证

先看一个问题,下面的myBlock指针指向的对像存储的位置,是在堆区、栈区、还是数据区?

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

先告诉大家结果,我也觉得很神奇,这个block对象存储的位置竟然是数据区。

为了验证Block在内存上的具体存储位置,我打印几个变量来辅助验证其存储位置,具体的看如下代码:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int height = 10.0;
        static int age = 20;
        BEPerson * person = [[BEPerson alloc] init];
        BEBlock myBlock = ^{
            NSLog(@"hello world");
        };

        NSLog(@"--address-- %p", &height);
        NSLog(@"--address-- %p", &age);
        NSLog(@"--address-- %p", &person);
        NSLog(@"--address-- %p", &myBlock);

        NSLog(@"\n\n");
        NSLog(@"---value--- %d", height);
        NSLog(@"---value--- %d", age);
        NSLog(@"---value--- %@", person);
        NSLog(@"---value--- %@", myBlock);
    }
    return 0;
}

打印结果:

 --address-- 0x7ffeefbff42c
 --address-- 0x100008124
 --address-- 0x7ffeefbff420
 --address-- 0x7ffeefbff418

 ---value--- 10
 ---value--- 20
 ---value--- <BEPerson: 0x101019570>
 ---value--- <__NSGlobalBlock__: 0x100004058>

结论:

heightpeeson指针myBlock指针都是0X7ffeebff--,所以它们3是存在栈区的。age用的是static变量来修饰的,所以其存在数据区。

然后看myBlock对象,其地址值是0x100004058age的地址0x100008124比较接近,所以可以判断,myBlock对象是存储在数据区的。 person对象,其地址值是0x101019570 ,存在堆区。

  • height是存在栈区
  • age在数据区
  • person指针是在栈区,但是其指向的对象,是在堆区
  • myBLock指针是在栈区,但是其指向的对象,是在数据区

参考资料:

深入理解iOS的Block

iOS底层原理