一、为什么进行内存管理
1、iOS应⽤用程序出现Crash(闪退),90%以上的原因是内存问题。
2、内存问题体现在两个⽅方⾯面:内存溢出、野指针异常。
3、iOS给每个应⽤用程序提供了⼀一定的内存,⽤用于程序的运⾏行。iPhone 3GS内存30M左右,iPhone 5S 内存80M左右。⼀一旦超出内存上限,程序就会Crash。
4、对象内存空间已经被系统回收,仍然使⽤用指针操作这块内存。野指针异常是程序crash的主要原因。代码量越大的程序,越难找出现野指针的位置。
二、什么样的需要我们去管理(谁开辟,谁管理)
在堆区开辟的空间,对象类型一般都是在堆区开辟空间。其他内存区域都不需要我们管理,比如静态区、常量区、栈区的空间。内存管理遵循的规则是谁开辟,谁管理。有开辟,就有回收。引用计数有加就得有对应的减少
三、内存管理的方式(gc、MRC、ARC)
gc:垃圾回收
MRC:⼈工引用计数
ARC:自动引用计数ARC仍然需要内存管理,只不过内存管理交给了编译器自己去做管理。
ARC下,不使用assign、retain、使用weak和strong。weak就相当于assign,但是比assign有一点好处就是能防止野指针,自动指向nil。strong就相当于retain。
四、内存管理的机制,引用计数、影响计数的方法
OC采用引用计数机制管理内存,当一个新的引用指向对象时,引用计数器就递增,当去掉⼀个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源
+alloc :开辟空间,引用计数从0变为1
-retain :引用计数加1
-copy :引用计数加1
-release :引用计数减1
-autorelease :引用计数在未来的某一时刻减1。当出池的时候@autoreleasepool{}
-dealloc :当引用计数变为0的时候自动调用,销毁该内存
五、内存管理的原则,当计数为零销毁(计数加减对应,又增加,必然有减少)
引用计数的增加和减少相等,当引⽤用计数降为0之后,不应该再使用这块内存空间。
凡是使⽤用了alloc、retain或者copy让内存的引用计数增加了,就需要使⽤用release或者autorelease让内存的引用计数减少。在一段代码
内,增加和减少的次数要相等。
六、retain与copy的区别,copy有哪些
跟retain不同,一个对象想要copy,⽣成⾃己的副本,需要实现NSCopying协议,定义copy的细节(如何copy)。如果类没有接受NSCopying协议⽽给对象发送copy消息,会引起crash。
要想实现copy,必须遵守NSCopying或者NSMutableCopying协议,这里面有一个必须实现的协议copyWithZone
copy分为深层copy和浅层copy
浅拷贝:就相当于retain,只拷贝一个对象的引用,相当于影子
深拷贝:重新开辟了一块内存空间用来存放原来对象里面的东西,这个时候copy出来的对象和原来对象不是同一个对象,相当于克隆人
拷贝出来的对象是什么类型取决于使用什么拷贝,可变拷贝,结果为可变对象。不可变拷贝为不可变对象
不可变copy拷贝不可变对象(浅拷贝)
不可变copy拷贝可变对象(深拷贝)
可变copy拷贝不可变对象(深拷贝)
可变copy拷贝可变对象(深拷贝)
属性的copy
copy修饰不可变属性的时候,就相当于retain
copy修饰可变属性的时候,相当于不可变copy拷贝可变对象,属于深拷贝,这个时候,属性和对象的内存都需要单独管理
七、属性retain和copy的set实现
retain的set方法
if(self.name!=name)
{
[_namerelease];
_name=[nameretain];
}
copy的set方法实现
if(self.name!=name)
{
[_namerelease];
_name=[namecopy];
}
八、delloc对属性释放(重写dello方法,回收属性开辟的空间)
如果对象释放之后,对象的实例变量开辟的空间没有得到释放,就会造成内存泄露。
如果想要安全释放,需要对实例变量依次释放,最后再释放对象。这样会很麻烦,
解决办法:我们通常在dealloc中释放类的实例变量。重写dealloc方法,在对象释放的时候对实例变量开辟的空间进行减1操作
self.name=nil;//相当于两个操作,先release,然后置空
九、便利构造器的内存管理(返回autorelease)
在便利构造器内部返回的时候retain [p autorelease];
十、collection的内存管理()
collection会自主管理自己内部的元素
加入collection中的对象会被retain
移除出collection的对象会被release
collection被释放会对内部所有对象release