美文网首页@IT·互联网iOS
Objective-C中Block内存分配全解析

Objective-C中Block内存分配全解析

作者: ChinaChong | 来源:发表于2018-09-12 16:52 被阅读20次

    Block的类

    设置对象的储存域
    _NSConcreteStackBlock 栈区
    _NSConcreteGlobalBlock 程序的数据区(全局区)
    _NSConcreteMallocBlock 堆区

    Block分配的规律

    Block不论在ARC下还是在MRC下,都会视情况被分配到这三种区中。我总结了分配在各种区的条件,如下:

    • NSConcreteGlobalBlock:无论此block是否被持有,block内没有引用外部变量
    • NSConcreteStackBlock: 此block必须未被持有,并且引用了外部变量
    • NSConcreteMallocBlock:此block必须被持有,并且引用了外部变量

    Block执行过copy后的情况

    Block的类 副本源的配置储存域 复制效果
    _NSConcreteStackBlock 栈区 从栈复制到堆
    _NSConcreteGlobalBlock 全局区 什么也不做
    _NSConcreteMallocBlock 堆区 引用计数增加

    栈上的Block什么时候会被复制到堆

    • 调用Block的copy实例方法
    • Block作为函数返回值返回时
    • 将Block赋值给附有__strong修饰符id类型的类或Block类型成员变量时
    • 在方法名中含有usingBlockCocoa框架方法或Grand Central Dispatch的API中传递Block时

    接下来就结合代码来分析Block的内存分配。

    等号左侧在OC默认情况下属于强指针,用__weak修饰后变成弱指针,右侧Block不会被持有,并且Block引用了外部变量,所以会被分配在栈区

    int temp = 10;
    __weak void(^blk_t1)(void) = ^{
        NSLog(@"%d",temp);
    };
    NSLog(@"1===%@",blk_t1);
    
    image.png

    等号左侧在OC默认情况下属于强指针,右侧block被持有,引用外部变量就分配在堆区

    int temp = 10;
    void(^blk_t)(void) = ^{
        NSLog(@"%d",temp);
    };
    blk_t();
    NSLog(@"2===%@",blk_t);
    
    image.png

    等号左侧在OC默认情况下属于强指针,右侧block被持有,不引用外部变量就分配在全局区

    void(^blk_tt)(void) = ^{
            
    };
    NSLog(@"3===%@",blk_tt);
    
    image.png

    此block未被持有,且引用了外部变量,所以分配在栈区

    int temp = 10;
    NSLog(@"4===%@",^{
        NSLog(@"%d",temp);
    });
    
    image.png

    栈区的block在执行copy后会被分配到堆区

    int temp = 10;
    NSLog(@"5===%@",[^{
        NSLog(@"%d",temp);
    } copy]);
    
    image.png

    等号左侧在OC默认情况下属于强指针,右侧block被持有,block内部未引用外部变量,被分配到全局区,执行copy后依然在全局区

    void (^blk_ttt)(void) = ^() {
        
    };
    blk_ttt();
    
    NSLog(@"\n6===\n拷贝前%@\n拷贝后%@",blk_ttt,[blk_ttt copy]);
    
    image.png

    block使用内部局部变量,未引用外部变量,依然是全局block

    void (^blk_tttt)(void) = ^{
        int b = 20;
        NSLog(@"%d",b);
    };
    blk_tttt();
    NSLog(@"7===%@",blk_tttt);
    
    image.png

    block内部使用传进来的参数,并不会持有该参数,此block在使用了参数后依然是全局block

    NSString *str = @"I love China!";
    void (^blk_ttttt)(NSString *) = ^(NSString *param){
        NSLog(@"%@",param);
    };
    blk_ttttt(str);
    NSLog(@"8===%@",blk_ttttt);
    
    image.png

    相关文章

      网友评论

        本文标题:Objective-C中Block内存分配全解析

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