如果要说iOS的内存管理问题,先要知道Objective-C是一门什么样的语言 —> Objective-C是一门面向对象的语言。
我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在Objective-C中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是由系统自己管理的,放在栈上入:int float 等)。如果一个对象创建并使用后没有得到及时释放那么就会占用大量内存。其他高级语言如C#、Java都是通过垃圾回收来(GC)解决这个问题的,但在Objective-C中并没有类似的垃圾回收机制,因此它的内存管理就需要由开发人员手动维护。今天将着重介绍Objective-C内存管理:
一、Objective-C 内存管理的对象
1、内存管理的对象主要有两类:
①基本数据类型:int 、float、 struct 等。
②引用类型:继承自NSObject类的所有Objective-C对象。
第一种基本数据类型不需要我们管理,第二种需要管理。2、管理内存的原理:
①值类型一般都会被放入栈中(先进后出),引用类型会被放到堆中,当给对象分配内存空间时,会随机从内存当中开辟空间,对象和对象之间可能会存在很多碎片,这些碎片空间需要我们管理。
②栈内存从性能上来说优于堆内存,数据量过大的时候,我们会把数据存入堆中,然后在栈中存放堆的地址,这样调用数据的时候,就可以快速的通过栈中的地址拿到堆中的数据。
③装箱:把int等包装成NSNumber(会降低性能);
拆箱:把NSNumber转化为float等 (注意类型错误时候的安全性问题);
装箱和拆箱会增加代码的运行时间,降低代码可读性,影响性能。
二、内存管理方式 主要是MRC和ARC管理方式;
- MRC:手动管理内存有时候并不容易,因为对象的引用有时候是错综复杂的,对象之间可能互相交叉引用,此时需要遵循一个法则:谁创建,谁释放。
- ARC:在Objective-C中也有一种内存自动释放的机制叫做“自动引用计数”(或“自动释放池”),与C#、Java不同的是,这只是一种半自动的机制,有些操作还是需要我们手动设置的。自动内存释放使用@autoreleasepool关键字声明一个代码块,如果一个对象在初始化时调用了autorelase方法,那么当代码块执行完之后,在块中调用过autorelease方法的对象都会自动调用一次release方法。这样一来就起到了自动释放的作用,同时对象的销毁过程也得到了延迟(统一调用release方法)。
autorelease方法不会改变对象的引用计数器,只是将这个对象放到自动释放池中;
自动释放池实质是当自动释放池销毁后调用对象的release方法,不一定就能销毁对象(例如如果一个对象的引用计数器>1则此时就无法销毁);
由于自动释放池最后统一销毁对象,因此如果一个操作比较占用内存(对象比较多或者对象占用资源比较多),最好不要放到自动释放池或者考虑放到多个自动释放池;
ObjC中类库中的静态方法一般都不需要手动释放,内部已经调用了autorelease方法;
三、MRC与ARC混编 在ARC项目中,对MRC文件可以添加 -fno-objc-arc标识;在MRC中,对ARC的文件可以添加 -fobjc-arc 的标识。(或者可以把MRC文件转为ARC,现在多用ARC,但是有些第三方框架还是MRC的需要处理);