美文网首页
Block内存分析

Block内存分析

作者: 简_爱SimpleLove | 来源:发表于2018-10-17 14:03 被阅读8次

    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<UITouch *> *)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内存分析

          本文链接:https://www.haomeiwen.com/subject/sfehzftx.html