Xcode 提供了2种内存管理方式:manual retain-release(MRR,手动管理)和 automatic reference counting(ARC,自动引用计数)。
ARC作为苹果新提供的技术,苹果推荐开发者使用ARC技术来管理内存;这篇笔记主要讲的是手动管理。
内存管理的目的是:
1.不要释放或者覆盖还在使用的内存,这会引起程序崩溃。
2.释放不再使用的内存,防止内存泄露。iOS程序的内存资源是宝贵的。
内存分5大区域:
1、栈区(stack ):由编译器自动分配释放,存放c函数的形参、局部变量的值等。
2、堆区(heap):一般由程序员分配释放,若程序员不释放,则程序结束时由操作系统回收。对象就存放在这,系统并不会及时地自动回收。
3、全局去(静态区,static):存放全局变量和静态局部变量。程序结束时由系统释放。
4、文字常量区:常量字符串就放在这。程序结束时由系统释放。
5、程序代码区:存放程序体的二进制代码。
手动管理内存也是基于引用计数的,只是需要开发者发消息给某块内存(或者说是对象)来改变这块内存的引用计数以实现内存管理(ARC技术则是编译器代替开发者完成相应的工作)。一块内存如果计数是零,也就是没有使用者(owner),那么objective-C的运行环境会自动回收这块内存。
objective-C的内存管理遵守下面这个简单的策略:
注:文档中把引用计数加1的操作称为“拥有”(own,或者take ownership of)某块对象/内存;把引用计数减1的操作称为放弃(relinquish)这块对象/内存。拥有对象时,你可以放心地读写或者返回对象;当对象被所有人放弃时,objective-C的运行环境会回收这个对象。
1.你拥有你创建的对象。
也就是说创建的对象(使用alloc,new,copy或者mutalbeCopy等方法)的初始引用计数是1。
2.给对象发送retain消息后,你拥有了这个对象。
3.当你不需要使用该对象时,发送release或者autorelease消息放弃这个对象。
4.不要对你不拥有的对象发送“放弃”的消息。
想拥有一个objective-C对象,必须发送“创建”或者retain消息给该对象。
野指针:指向僵尸对象(不可用内存空间)的指针(多是因为有多余的release操作造成)。
运行时若出现error信息:EXC_BAD_ACCESS: 则为访问了一块坏内存(已经被回收,不可用内存),也叫野指针错误。
解决方法:当retainCount为0后,加上一句p = nil; 使其成为空指针即可。
OC中不存在空指针错误,因为给空指针发送消息,不报错。但给野指针发送消息,会报错。
@interface Counter : NSObject
@property (nonatomic, retain) NSNumber *count;
@end
一、getter方法仅仅返回成员变量就可以:
-(NSNumber *)count
{
return _count;
}
二、set方法的代码规范:
1、基本数据类型,可直接赋值。
- (void)setAge: (int)age
{
_age = age;
}
2、OC对象类型:
- (void)setCar: (Car *)car
{
if (car != _car)
{
[_car release];
_car = [car retain];
}
}
特别注意:
在@property的参数里加上retain,生成的set方法里,就会自动release旧值,retain新值。
三、dealloc方法
dealloc方法用来释放这个对象所占的内存(包括成员变量)和其它资源。
dealloc方法的代码规范:
1、一定要写[super dealloc], 而且要将其放到最后面。
2、对 self 当前对象所拥有的其他对象做一次release
- (void)dealloc
{
[_car release];
[super dealloc];
}
四、Autorelease Pool
Autorelease Pool可以延后发送release消息给一个对象。发送一个autorelease消息给一个对象,相当于说这个对象在“一定时期”内都有效,“一定时期”后再release这个对象。
@autoreleasepool
{
Person *p = [[[Person alloc]init]autorelease];
p.age = 10;
}
自动释放池可创建无数多个,是半自动的。
autorelease方法会返回对象本身,将对象放入一个自动释放池中,当池子销毁时,会对池子当中的所有对象做一次release操作。
用于占用内存小的对象,没有太大影响,因为其不能灵活地释放对象。
调用完autorelease后,对象的计数器不变。
好处:
不用再关心对象的释放时间,不用再关心什么时候调用release。