在说Block内存管理之前,先提个问题,Block是不是一个对象?
Block是一个对象
为什么呢?苹果官方文档给出了答案
具体解释链接https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html
Block内存管理分为MRC何ARC, 此篇文章介绍Block在MRC环境下的内存管理。
当我们打开一个工程文件时,如何判断当前项目是ARC或者MRC呢?
1、在dealloc 方法中看是否能调用super, 只有在MRC环境下才能调用super。
2、能否可以使用retain,release,如果可以使用就是MRC。MRC开发了解常识
1、MRC没有strong weak,局部变量对象相当于基本数据类型。
2、MRC给成员属性赋值,一定要调用setter方法,不能直接访问实例变量来赋值。(调用setter方法,会做很多事情,否则会造成内存泄漏)
言归正传,下面介绍MRC环境下Block的内存管理。
1、新建工程,默认ARC环境,设置为MRC环境。
2、定义一个block
-
Block 没有引用局部变量
void(^block)(void) = ^{ }; NSLog(@"%@", block);
打印结果为:
<__NSGlobalBlock__: 0x106350088>
由此可以看出此时Block放在全局区
-
Block 引用局部变量
NSInteger index = 0; void(^block)(void) = ^{ NSLog(@"%ld", index); }; NSLog(@"%@", block);
打印结果为:
<__NSStackBlock__: 0x7ffee143fa28>
由此可以看出此时Block放在栈区
-
Block 引用静态变量
static NSInteger index = 0; void(^block)(void) = ^{ NSLog(@"%ld", index); }; NSLog(@"%@", block);
打印结果为:
<__NSGlobalBlock__: 0x10136b070>
由此可以看出此时Block放在全局区
-
Block 引用全局变量
NSInteger a = 0;//全局变量 void(^block)(void) = ^{ NSLog(@"%ld", a); }; NSLog(@"%@", block);
打印结果为:
<__NSGlobalBlock__: 0x104905070>
由此可以看出此时Block放在全局区
3、定义属性保存Block
@property (nonatomic, retain) void(^block)(void);
int a = 0;
void(^block)(void) = ^{
NSLog(@"%d", a);
};
self.block = block;
NSLog(@"%@", self.block);
打印结果为:
<__NSStackBlock__: 0x7ffeedd1da28>
此时再去访问self.block, 就会出现崩溃
使用retain修饰block,此时block还在栈里
总结
只要block没有引用外部局部变量,block放在全局区
只要Block引用外部局部变量,block放在栈里面.
block只能使用copy,不能使用retain