iOS内存管理的知识梳理
从作用上来说,手机内存小,划分给每个App的内存有限,合理的进行内存管理,有利于提高软件的运行性能和用户体验;
另外,内存管理是一大理论知识块,对这块知识的理解程度也是考核面试者的重要标准。
内存管理,给稍微有些经验的开发者的感觉就是既无处不在,但是又没在内存管理上没花过心思。
说它无处不在,那是因为从你定义一个属性开始、从你实例化一个对象开始,内存管理就已经起作用了。
说开发过程中没有为它花过心思吧,那是因为只有有一套固定的编程习惯,基本也就不用停下敲键盘的手指,认真思考一番。因为在这套习惯中,把内存管理的使用方法和避免bug的方式都融入进去了。
本文的定位是梳理下作为一个iOS开发者,如果有人问起你内存管理方面的知识,你能顺着这个大纲,把大致的内容能够勾勒出来。
我认为内存管理主要是以下五个方面的内容块:
(一)数据存储空间
首先分为栈区、堆区、静态区、常量区、代码区,需要知道每个存储区的作用和区别。
然后进一步明白内存管理,其实就是管理堆区。
(二)引用计数管理方式
Objective-C中使用的是引用计数的管理方式。不管是手动管理(MRC)还是自动管理(ARC),对这几个概念要有清晰的认识:
生成对象、生成并持有对象、生成但不持有对象、持有对象、释放对象、废弃对象。手动或者自动管理都只是实现方式。引用计数式内存管理的思考方式,有比较经典的话就是:
- 自己生成的对象,自己所持有。
- 非自己生成的对象,自己也能持有。
- 自己持有的对象不再需要时释放。
- 非自己持有的对象无法释放。
然后就是手动模式的实现方式中使用的:alloc/new/copy/mutableCopy等方法、retain方法、release方法、dealloc方法。
最后就是自动模式的实现方式中使用的:__strong修饰符、__weak修饰符、__unsafe_unretained修饰符、__autoreleasing修饰符。
另外,对一个文件使用MRC还是ARC模式进行编译,是可以进行切换的。
(三)深拷贝和浅拷贝
在体会好“生成对象”和“持有对象”之后,可以弄明白深拷贝和浅拷贝的机制。
也就明白了是否是深拷贝还是浅拷贝不仅仅看的是用得是copy还是mutableCopy,还得看被拷贝的是可变还是不可变对象。
(四)属性限定符的使用
因为Objective-C的封装理念,把对象的状态用属性的方式封装起来。那些自动模式下使用的修饰符(比如__weak),对应在属性上就是属性限定符。比如strong/weak/assign/copy/retain,之前的那些修饰符弄明白的情况下,使用这些属性限定符也就很清晰了。
(五)内存泄漏问题
如果没有把上面内存管理的方法充分理解和熟练使用,造成的对应问题就是内存泄漏。
内存泄漏的场景包括:
对象型变量作为C语言结构体(struct、union)的成员;
循环引用;
单例属性不释放;
等。
内存泄漏的检测方法包括:
Xcode中自带的Instrument工具;
利用类中的dealloc方法进行打印;
等。