Block内存管理

不引用任何外部变量的 block

- (void)blockDemo1 {

    void(^myBlock)() = ^ {
        NSLog(@"hello world");
    };

    NSLog(@"%@", myBlock);
}

不引用任何外部变量的 block 保存在全局区 NSGlobalBlock

如果Block没有引用外部变量,那么这个Block的函数体内部包装的代码都不会发生变化,而且执行效率高,保存在全局区;(类似不变的字符串)

但是实际开发中,不引用外部变量的 block 几乎是不存在的

引用外部变量的 block

- (void)blockDemo2 {

    int i = 10;

    void(^myBlock)() = ^ {
        NSLog(@"hello world %zd", i);
    };

    NSLog(@"%@", myBlock);
}

引用外部变量的 block 保存在 :

ARC : 堆区 NSMallocBlock

MRC : 栈区 NSStackBlock

因此 : 在定义 block 属性时应该使用 copy 关键字,将 block 从栈区复制到堆区

定义 block 属性

/// 定义 block 属性
@property (nonatomic, copy) void (^demoBlock)();

记录 block 属性

- (void)blockDemo2 {

    int i = 10;

    void(^myBlock)() = ^ {
        NSLog(@"hello world %zd", i);
    };

    NSLog(@"%@", myBlock);

    // 错误的写法,不会调用 setter 方法,MRC下,无法拷贝到堆区
    // _demoBlock = myBlock;

    // 正确的写法,调用 setter 方法,并且对 block 进行 copy
    self.demoBlock = myBlock;

    NSLog(@"%@", self.demoBlock);
}

提示 : 为了避免程序员的麻烦,在 ARC 中,定义了引用外部变量的 block,系统默认都是在堆区的!

补充 : 仅做课外了解

演示Block : 分别在MRCARC环境下,使用成员变量和属性时的区别

  • 此方法是演示MRC环境 (仅做课外了解)
- (void)blockDemo4
{
    int num = 10;

    void (^task)() = ^ {
        NSLog(@"%d",num);
    };

    // MRC : 栈区 ==> __NSStackBlock__

    // 这个赋值过程会copy,也会引用计数+1
//    self.task = task;
    // 这个赋值过程不会copy,仅仅是引用计数+1,内存依然在栈区
    _task = task;

    // 在MRC环境下,调用成员变量进行赋值,仅仅是引用计数加1;不会进行copy操作!!!!!

    NSLog(@"%@ -- %@",task,_task);
}
  • 此方法是演示ARC环境 (仅做课外了解)
- (void)blockDemo3
{
    int num = 10;

    void (^task)() = ^ {
        NSLog(@"%d",num);
    };

    // ARC : 堆区 ==> __NSMallocBlock__

    // ARC环境下,属性也是强引用,同时会copy
//    self.task = task;
    // ARC环境下,成员变量也是强引用,同时会copy
    _task = task;

    // <__NSMallocBlock__: 0x7fc24150cae0> -- <__NSMallocBlock__: 0x7fc24150cae0>
    // 因为在ARC环境下,上述block本来保存在堆区,给属性赋值的时候,调用setter方法时,会给一个引用;
    // 提示 : 在ARC环境下,使用strong和copy的效果是一毛一样的!
    NSLog(@"%@ -- %@",task,_task);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值