在本章,你将学到:
ide
复习旧的手工内存管理的策略性能
对象全部权策略学习
基于旧的手工内存管理之上的新的自动内存管理优化
什么是对象的拷贝以及如何使用它spa
如何恰当的使用autorelease和release方法对象
复习内存测量blog
iPhone是一个内存有限的环境。可是,不少开发者要么低估了它,要么高估了它,所以并无利用好iPhone上的可用内存来提高性能。还有一些开发者很是担忧iPhone上的内存和性能,以致于他们过分优化,这样其实对代码的可阅读性是很是有害的,也使得往后的维护变得更加困难。
事件
为了有效利用内存来提高性能,同时使代码更容易阅读,又不让应用崩溃,你须要理解iPhone环境下的内存结构。你须要学习如何避免在内存在中过多引用对象,它可以致使内存警告和程序崩溃。你一样须要知道什么时候retain或release一个对象;若是在内存中的对象太少,可能会使得你的计算变得缓慢,由于你须要从新构造对象或从文件系统中加载。内存
简单的回顾开发
本部分是学习新的自动引用计数(ARC)的一个很好的过渡。有些人可能对于转到新的课程会有些迷惑。我但愿本部分可以帮助你很是顺利的过渡到新的ARC机制上。
旧的对象全部权策略
若是A对象有B对象的一个强引用,那么A对象须要手动的release对象B,这是旧的概念。若是A对象alloc,copy,mutableCopy,new或retain对象B,那么A对象就有了对象B的强引用。另外一方面,若是A对象没有使用这些方法,那么A对象拥有B对象的弱引用。
对于旧的内存管理机制,若是你的对象或方法有另外一个对象B的强引用,你有责任release或autorelease对象B。每个B对象的强引用都会使得它的引用计数加1。若是没有任何对象拥有B对象的强引用,换句话说,B对象的引用计算为0,B对象就会被deallocated(Listing 7.1)。
Listing 7.1. Release the Object if You Have a Strong Reference
- (void)doSomething {
NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj: %@", obj);
[obj release];
}
AutoRelease
autorelease方法会将对象发送到一个池中,而后声明这个对象稍后将要被release掉。使用这个方法,你不想拥有任何对象的强引用,可是你也不想它被dellocated。请查看Listing 7.2 。
Listing 7.2. Memory Issue
- (NSObject *)getObj {
NSObject *obj = [[NSObject alloc] init];
return obj;
}
- (void)anotherMethod {
NSObject *myObj = [self getObj];
// do something
// Should I release the object here?
[myObj release];
}
如今,在你使用完一个对象后,你要问问本身是否须要release它。一般,你可能会认为要release它;不然,没人release它,那么就会发生内存泄露。可是,由于你的anotherMethod方法没有myObj的强引用,你不能release myObj。惟一的办法就是像Listing 7.3 使用autorelease。
Listing 7.3. Use Autorelease to Solve the Problem
- (NSObject *)getObj {
NSObject *obj = [[NSObject alloc] init];
return [obj autorelease];
}
- (void)anotherMethod {
NSObject *myObj = [self getObj];
// do something
}
注意:anotherMethod没有其余对象的强引用。 |
Autorelease
我会快速的带你复习一下autorelease pools,而后深刻的解释一下相关概念,这样你就可以理解autorelease pool和release之间的不一样。
autorelease pool是存放autoreleased对象的地方。当这个autorelease pool被release时,全部的autoreleased对象会发送一个release消息。若是一个对象的引用计数为0,那个这个对象就会被deallocted。
在事件声明周期结束的时候,autorelease pool会被release。例如,当用户触摸了UI,一个新的事件声明周期会被建立来处理此次触摸事件,而后它处理相关触摸事件的全部理解,最后显示给用户。这就是一个事件声明周期。对于这个事件声明周期,你会有一个autorelease poo。
在main 方法中建立一个main autorelease pool,可使用下面的代码:
int main(int argc, char *argv[]) {
@autoreleasepool {
int retVal = UIApplicationMain(argc, argv, nil, nil);
}
return retVal;
}
在代码中能够看到,在方法的开始部分,建立了一个新的autorelease pool,使用了UIApplicationMain处理了主要的逻辑;在事件循环以后,pool被release。整个周期如图7-1.