iOS底层 -- Blcok本质之Block的类型

Block有3种类型,可以通过调用class方法或者isa指针查看具体类型,最终都是继承自NSBlock类型

  • NSGlobalBlock ( _NSConcreteGlobalBlock )
  • NSStackBlock ( _NSConcreteStackBlock )
  • NSMallocBlock ( _NSConcreteMallocBlock )

一.Block对象的存储区域

Block的类型 对象的存储域
NSGlobalBlock 程序的数据区域(.data)
NSStackBlock
NSMallocBlock

二.判断Block的类型

Block的类型 环境
NSGlobalBlock 没有访问auto变量
NSStackBlock 访问了auto变量
NSMallocBlock NSStackBlock调用了copy

三.Block调用copy操作

Block的类型 对象的存储域 复制效果
NSGlobalBlock 程序的数据区域 什么也不做
NSStackBlock 从栈复制到堆
NSMallocBlock 引用计数增加

四.ARC环境下自动为Block进行copy操作的情况

1.block作为函数返回值时

typedef void(^Block)(void);

Block test() {
    int age = 10;
    return ^{
        NSLog(@"age=%d", age);
    };
}

int main(int argc, char * argv[]) {
    @autoreleasepool {
        Block block = test();
        block();
        return 0;
    }
}

2.将block赋值给__strong指针时

void (^block)(void);

void test() {
    int age = 10;
    block = ^{
        NSLog(@"age=%d", age);
    };
}

int main(int argc, char * argv[]) {
    @autoreleasepool {
        test();
        block();
        return 0;
    }
}

3.block作为Cocoa API中方法名含有usingBlock的方法参数时

NSArray *array = [[NSArray alloc] init];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSLog(@"%d", idx);
}];

4.block作为GCD API的方法参数时

dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"1111");
});

你可能感兴趣的:(iOS底层 -- Blcok本质之Block的类型)