内存管理

OC内存管理
一、基本原理
(一)为什么要进行内存管理。
由于移动设备的内存极其有限,所以每个 APP 所占的内存也是有限制的,当 app 所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等。
管理范围: 任何继承NSObject的对象,对其他的基本数据类型无效。
本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也被回收,此时对象已经没有指针指向,但依然存在于内存中,造成内存泄露。
 
(二)对象的基本结构
每个 OC 对象都有自己的引用计数器,是一个整数表示对象被引用的次数,即现在有多少东西在使用这个对象。对象刚被创建时,默认计数器值为 1 ,当计数器的值变为 0 时,则对象销毁。
在每个 OC 对象内部,都专门有 4 个字节 的存储空间来存储引用计数器。
 
(三)引用计数器的作用
判断对象要不要回收的唯一依据就是计数器是否为 0 ,若不为 0 则存在。
 
(四)操作
给对象发送消息,进行相应的计数器操作。
Retain 消息:使计数器 +1 ,该方法返回对象本身
Release 消息:使计数器 -1 (并不代表释放对象)
retainCount 消息:获得对象当前的引用计数器值
 
(五) 对象的销毁
当一个对象的引用计数器为 0 时,那么它将被销毁,其占用的内存被系统回收。
当对象被销毁时,系统会自动向对象发送一条 dealloc 消息,一般会重写 dealloc 方法,在这里释放相关的资源, dealloc 就像是对象的“临终遗言”。一旦重写了 dealloc 方法就必须调用 [super dealloc] ,并且放在代码块的最后调用(不能直接调用 dealloc 方法)。
一旦对象被回收了,那么他所占据的存储空间就不再可用,坚持使用会导致程序崩溃(野指针错误)。
 
二、相关概念和使用注意
野指针错误:访问了一块坏的内存(已经被回收的,不可用的内存)。
僵尸对象:所占内存已经被回收的对象,僵尸对象不能再被使用。(打开僵尸对象检测)

空指针:没有指向任何东西的指针(存储的东西是 0,null nil ),给空指针发送消息不会报错
注意:不能使用 [p retaion] 让僵尸对象起死复生
 
三、内存管理原则
(一)原则
只要还有人在使用某个对象,那么这个对象就不会被回收;
只要你想使用这个对象,那么就应该让这个对象的引用计数器 +1
当你不想使用这个对象时,应该让对象的引用计数器 -1
(二)谁创建,谁release
(1)如果你通过 alloc,new,copy 来创建了一个对象,那么你就必须调用 release 或者 autorelease 方法
(2)不是你创建的就不用你去负责
(三)谁retain,谁release
只要你调用了 retain ,无论这个对象时如何生成的,你都要调用 release
(四)总结
有始有终,有加就应该有减。曾经让某个对象计数器加 1 ,就应该让其在最后 -1.
 
四、内存管理代码规范
(一)只要调用了alloc,就必须有release(autorelease)
(二)Set方法的代码规范
(1)基本数据类型:直接复制
- void setAge:(int)age
{
_age=age;
}
(2)OC 对象类型
- void setCar:(Car *)car
{
//1. 先判断是不是新传进来的对象
If(car!=_car)
{
//2  对旧对象做一次 release
[_car release];// 若没有旧对象,则没有影响
//3. 对新对象做一次 retain
_car=[car retain];
}
}
(三)dealloc方法的代码规范
(1) 一定要[super dealloc],而且要放到最后
(2)对 self (当前)所拥有的的其他对象做一次 release 操作
- void dealloc
{
[_car release];
[super dealloc];
}
五、@property的参数
(1)内存管理相关参数
Retain: 对对象 release 旧值, retain 新值(适用于 OC 对象类型)
Assign: 直接赋值(默认,适用于非 oc 对象类型)
Copy:release 旧值, copy 新值
 
(2)是否要生成 set 方法(若为只读属性,则不生成)
Readonly: 只读,只会生成 getter 的声明和实现
Readwrite: 默认的,同时生成 setter getter 的声明和实现
 
(3)多线程管理(苹果在一定程度上屏蔽了多线程操作)
Nonatomic: 高性能,一般使用这个
Atomic: 低性能
 
(4)Set get 方法的名称
修改 set get 方法的名称,主要用于布尔类型。因为返回布尔类型的方法名一般以 is 开头,修改名称一般用在布尔类型中的 getter
@propery(setter=setAbc,getter=isRich) BOOL rich;
BOOL b=p.isRich;//  调用
 
六、内存管理中的循环引用问题以及解决
案例:每个人有一张身份证,每张身份证对应一个人,不能使用 #import 的方式相互包含,这就形成了循环引用。
新的关键字:@class 类名;——解决循环引用问题,提高性能
@class 仅仅告诉编译器,在进行编译的时候把后面的名字作为一个类来处理。
1 @class 的作用:声明一个类,告诉编译器某个名称是一个类
2 )开发中引用一个类的规范
1 )在 .h 文件中使用 @class 来声明类
2 )在 .m 文件中真正要使用到的时候,使用 #import 来包含类中的所有东西
3 )两端循环引用的解决方法
一端使用retain,一端使用assign(使用assign的在dealloc中也不用再release
 
七、Autorelease
(一)基本用法
(1)会将对象放到一个自动释放池中
(2)当自动释放池被销毁时,会对池子里的所有对象做一次 release
(3)会返回对象本身
(4)调用完 autorelease 方法后,对象的计数器不受影响(销毁时影响)
(二)好处
(1)不需要再关心对象释放的时间
(2)不需要再关心什么时候调用 release
(三)使用注意
(1)占用内存较大的对象,不要随便使用 autorelease ,应该使用 release 来精确控制
(2)占用内存较小的对象使用 autorelease ,没有太大的影响
(四)错误写法
(1)连续调用多次 autorelease ,释放池销毁时执行两次 release(-1 吗? )
(2)Alloc 之后调用了 autorelease ,之后又调用了 release
(五)自动释放池
(1)在 ios 程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的。
(2)当一个对象调用 autorelease 时,会将这个对象放到位于栈顶的释放池中
(六)自动释放池的创建方式
(1)ios 5.0 以前的创建方式
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
`````````````````
[pool  release];//[pool drain]; 用于 mac 
(2)Ios5.0 以后
@autoreleasepool
{// 开始代表创建自动释放池
·······
}// 结束代表销毁自动释放池
(七)Autorelease注意
(1)系统自带的方法中,如果不包含 alloc new copy 等,则这些方法返回的对象都是 autorelease 的,如 [NSDate  date]
(2)开发中经常会写一些类方法来快速创建一个 autorelease 对象,创建对象时不要直接使用类名,而是使用 self
 
 
八、ARC内存管理机制
(一)ARC的判断准则:
只要没有强指针指向对象,对象就会被释放。
(二)指针分类:
(1)强指针:默认的情况下,所有的指针都是强指针,关键字 strong
(2)弱指针: _ _weak 关键字修饰的指针
声明一个弱指针如下:
_ _weak Person *p;
ARC 中,只要弱指针指向的对象不在了,就直接把弱指针做清空操作。
_ _weak Person *p=[[Person alloc]  init];// 不合理,对象一创建出来就被释放掉,对象释放掉后, ARC 把指针自动清零。
ARC 中在 property 处不再使用 retain, 而是使用 strong ,在 dealloc 中不需要再 [super dealloc]
@property nonatomic,strong Dog *dog;//  意味着生成的成员变量 _dog 是一个强指针,相当于以前的 retain
如果换成是弱指针,则换成 weak ,不需要加 _ _
 
(三)ARC的特点总结:
(1)不允许调用 release retain retainCount 
(2)不允许重写 dealloc, 但是不允许调用 [super dealloc]
(3)@property 的参数:
Strong: 相当于原来的 retain (适用于 OC 对象类型),成员变量是强指针
Weak: 相当于原来的 assign,( 适用于 oc 对象类型 ) ,成员变量是弱指针
Assign :适用于非 OC 对象类型(基础类型)
(四)补充
让程序兼容 ARC 和非 ARC 部分。转变为非 ARC  -fno-objc-arc   转变为 ARC 的,  -f-objc-arc 
ARC 也需要考虑循环引用问题:一端使用 retain ,另一端使用 assign

提示:字符串是特殊的对象,但不需要使用 release 手动释放,这种字符串对象默认就是 autorelease 的,不用额外的去管内存。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值