Block内存分析

1. block的层级

Block就是一个里面存储了指向函数体中包含定义block时的代码块的函数指针,以及block外部上下文变量等信息的结构体。 它是一个object对象,可以通过可以通过object_getClass 来获取对象的class。
通过以下方法,就能获得block的层级

- (void)logBlockIsObject {
    int i = 10;
    void (^tmpBlock)(void) = ^{
        NSLog(@"i = %d", i);
    };
    
    Class blockClass = object_getClass(tmpBlock);
    while (blockClass) {
        NSLog(@"class = %@", blockClass);
        blockClass = class_getSuperclass(blockClass);
    }
}

打印出tmpBlock的类的层级:NSMallocBlock 、__NSMallocBlock 、NSBlock、NSObject

2. block内存分析

block的内存分布:block有三种种类:globalBlock(全局)、mallocBlock(堆区)、stackBlock(栈区)
1、没有外部变量的block:统统都属于globalBlock
2、有外部变量的情况:

  • 2.1 全局变量、全局静态变量、局部静态变量(统统都是globalBlock);
  • 2.2 普通的外部变量: strong和copy修饰的是一样的,为mallocBlock(在堆区);weak修饰的,为stackBlock,在栈区

3、如果block作为自定义函数参数,block在栈区;系统的函数,会把block转移到mallocblock,也就是堆区

注意1:当block为globalBlock时,哪怕是用weak修饰的block,依然能够调用成功。如下:

- (void)blockMemory {
    static int tempPartValue = 10;
    _strongBlock = ^{
        NSLog(@"_strongBlock - %d", globalValue);
    };
    _copyBlock = ^{
        NSLog(@"_copyBlock - %d", globalValue);
    };
    _weakBlock = ^{
//        NSLog(@"_weakBlock - %d", globalValue);
        NSLog(@"_weakBlock");
    };
    
    NSLog(@"_strongBlock : %@,_copyBlock : %@,_weakBlock : %@", object_getClass(_strongBlock), object_getClass(_copyBlock), object_getClass(_weakBlock));
    
    _strongBlock1 = ^(int i) {
        NSLog(@"_strongBlock1 : i=%d", i);
    };
    _copyBlock1 = ^(int i) {
        NSLog(@"_copyBlock1 : i=%d", i);
    };
    _weakBlock1 = ^(int i) {
        NSLog(@"_weakBlock1 : i=%d", i);
    };
    NSLog(@"strongBlock1 %@, copyBlock1 %@, weakBlock1 %@", object_getClass(_strongBlock1), object_getClass(_copyBlock1), object_getClass(_weakBlock1));
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    _weakBlock();
}

在touchesBegan方法中调用_weakBlock,依然能够打印成功。


image.png

注意2:当block在栈区的时候,也就是为stackBlock的时候,再调用block会报错,因为已经被释放了。
注意3:你自定义的函数,block作为参数,block会是在栈区;但是如果你调用了系统的方法,block它会自动copy,变成mallocblock。如下:


image.png

object_getClass 类似这样的方法,只要不是自己写的,都是系统的方法。

注意4:作为返回值的block,情况和上面一样

  • 当没有外部变量或者有全局变量、全局静态变量、局部静态变量(统统都是globalBlock)。
  • 当有普通外部变量的时候,是 mallocblock。
    如下:


    全局静态变量
普通外部变量

你可能感兴趣的:(Block内存分析)