Objective-C 之内存管理

2016-01-27  本文已影响55人  CarsonChen

一. 内存管理的方式

1. 内存溢出

应用程序所加载的文件总和超过iOS系统分配的程序固定的RAM,引起的Crash,用户端体验则为闪退至桌面.

2. 野指针异常

对象的内存已被系统回收,但是仍然要通过指针来操作这块内存.引起Crash.

3. 内存的管理方式

a. 垃圾回收机制(Java开发一直使用) :程序员只需要开辟内存空间,不需要进行是否,由系统判断何时释放内存空间.

b. MRC:人工引用计数,内存开辟和释放空间由程序代码控制.相对垃圾回收机制来说,内存的回收相对灵活.对程序员的要求也很高,程序员要属性内存管理机制.

c. ARC:自动引用计数:iOS5.0后编译器的特性,至允许程序员开辟空间,不许程序员写释放空间的代码片段,简化开发成本.注:释放空间的代码有编译器自动添加.

d. iOS支持的两种内存管理方式:MRC与ARC.

e. MRC的内存管理机制为:引用计数

f. ARC是基于MRC的.

二. 引用计数机制,影响引用计数的各种方法

1. 引用计数机制

(前言)C语言中,无法记录多个指针指向同一内存地址的个数,只能通过指针进行开辟堆空间操作以及释放堆空间的操作.实际开发过程中,有多个指针指向同一内存单元.

a. OC中采用引用计数机制管理内存,每个对象都有一个引用计数器,用来记录当前对象的引用次数.原理:当一个新的引用指向对象时,引用计数器就+1,去掉一个引用时,引用计数器就-1,当引用计数器为0时,该对象的空间就会被系统回收释放. 

b. retainCount返回的为该对象的引用值.(注意:自定义类实例化对象的引用值正常,若是系统类声明的对象,则可能返回的值不一定正常,或许系统其它框架的对象对其对象有所有权,则导致值与预期所想的不一致)

2. 影响引用计数的方法

a. 引用计数的步骤:

生成对象: +alloc   

开辟内存空间,让被开辟内存空间的引用计数从0变至1

持有对象: -retain

调用一次该方法,该对象被持有一次所有权,则引用计数+1

释放对象: -release / -autorelease

release方法执行后,该对象的应用值立刻-1,-autorelease方法执行后,则在将来的某一时刻该对象的引用值-1,即对象调用autorelease方法后,对象则被添加到离autorelease方法最近的autoreleasepool(自动释放池)中,当自动释放池销毁时,为池中的每一个对象发送release方法.

销毁对象: -dealloc

b. copy 把某一对象的内容进行拷贝,原对象引用纸不变,新对象的引用值+1.

3. iOS5.0之前使用NSAutoReleasePool类创建对象,之后采用 @autoreleasepool{}代替,出了大括号,即自动释放池被回收,其中的对象同一被发送release消息.

4. dealloc方法为NSObject类的方法,即:当引用值为0的时候,销毁该对象使用的空间,重写dealloc方法,切记要[super dealloc],上方添加所需代码.

三. 内存管理的基本原则

1. 凡是使用了alloc,copy,contain的方法都是让内存引用增加了,所以都必须使用release与autorelease方法让内存引用减少,在一段代码片段内,增加和减少的次数要相等.

2. 如果增加的次数大于减少的次数,则会导致内存泄露.

3. 如果增加的次数小于减少的次数,会导致过度释放.

4. 如果增加的次数等于减少的次数,但还能继续访问,会造成野指针问题.

四. 协议(类似Java中的接口)

1. Protocol(为一堆方法的声明),即只有.h文件,类似于一张任务清单,清单交给谁,谁就要完成该清单上的方法.

2. 接受协议的类实现协议中的方法.

3. 协议中@required修饰的方法,在类中必须实现,@optional的方法,在类中可选择性的实现.

4. 类遵守协议即在类的声明部分父类后边使用"<Protocol>"使用遵循多个协议时即:<Protocol1,Protocol2,....>

5. 协议的优点:让接受协议的类间接扩展了实例方法,因为一个类可以同时遵守n个协议,所以可以解决OC中类无法多继承的问题.

五. 内存拷贝

1. 一个对象要想进行拷贝必须服从NSCopying协议,定义copy的方法,如果类没有接受NSCopying协议发送copy消息,则会发生Crash.

2. NSCopying协议中为定义- (id)copyWithZone:(NSZone *)zone;方法,该方法分为三种类型.

a. 伪拷贝

伪拷贝相当于进行了retain的操作,使得该内存空间的引用数+1

- (id)copyWithZone:(NSZone *)zone {

return [self retain];

}

b. 浅拷贝

浅拷贝则为内存中出现了两个一模一样的对象,但是两个对象的实例变量指向的是同一空间.

c. 深拷贝

深拷贝则为内存中出现了两个一模一样的对象,两个对象的实例变量指向不同的空间.

3. mutableCopy方法返回的结果是一个一模一样的对象,在内存中的不同的单元.即clone出来的对象.

上一篇 下一篇

猜你喜欢

热点阅读