Mat*_*ard 122 memory iphone cocoa objective-c
我刚开始看看Objective-C和Cocoa,以便玩iPhone SDK.我对C malloc和free概念感到相当舒服,但Cocoa的引用计数方案让我很困惑.一旦你理解了它,我就被告知它非常优雅,但我还没有超过驼峰.
怎么办release,retain和autorelease工作有什么关于他们使用的约定?
(或者失败了,你读了什么帮助你得到它?)
Mat*_*ard 148
让我们从retain和开始release; autorelease一旦你理解了基本概念,这真的只是一个特例.
在Cocoa中,每个对象都会跟踪它被引用的次数(具体来说,NSObject基类实现了这一点).通过调用retain一个对象,您告诉它您希望将其引用计数加1.通过调用release,您告诉对象您放弃它,并且它的引用计数递减.如果在调用之后release引用计数现在为零,则系统将释放该对象的内存.
这与它的基本方式不同,malloc并且free任何给定的对象都不需要担心系统崩溃的其他部分,因为你已经释放了他们正在使用的内存.假设每个人都在按照规则进行游戏并保留/释放,当一段代码保留然后释放该对象时,任何其他引用该对象的代码都不会受到影响.
什么有时会混淆是知道下,你应该调用情况retain和release.我的一般经验法则是,如果我想在一个对象上持续一段时间(例如,如果它是类中的成员变量),那么我需要确保对象的引用计数知道我.如上所述,通过调用增加对象的引用计数retain.按照惯例,当使用"init"方法创建对象时,它也会递增(实际上设置为1).在这些情况中的任何一种情况下,release当我完成它时,我有责任调用该对象.如果我不这样做,就会出现内存泄漏.
对象创建示例:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Run Code Online (Sandbox Code Playgroud)
现在为autorelease.Autorelease用作方便(有时是必要的)方式告诉系统在一段时间后释放此对象.从管道的角度来看,当autorelease被调用时,当前线程会NSAutoreleasePool被警告该呼叫.在NSAutoreleasePool现在知道,一旦它得到一个机会(事件循环的当前迭代之后),它可以调用release的对象.从我们作为程序员的角度来看,它需要照顾release我们,所以我们没有(事实上,我们不应该).
需要注意的是,(按照惯例),所有对象创建类方法都返回一个自动释放的对象.例如,在以下示例中,变量"s"的引用计数为1,但在事件循环完成后,它将被销毁.
NSString* s = [NSString stringWithString:@"Hello World"];
Run Code Online (Sandbox Code Playgroud)
如果要挂起该字符串,则需要retain显式调用,然后release在完成后显式调用.
考虑以下(非常人为的)代码,您将看到需要的情况autorelease:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
Run Code Online (Sandbox Code Playgroud)
我意识到所有这一切都有点令人困惑 - 但在某些时候,它会点击.以下是一些可以帮助您前进的参考资料:
And*_*ant 10
如果您了解保留/释放的过程,那么对于已建立的Cocoa程序员来说,有两个很明显的"黄色"规则,但不幸的是,对于新手来说很少明白这一点.
如果返回一个对象的函数有alloc,create或者copy在其名称中,那么该对象就是你的.完成后你必须打电话[object release].或者CFRelease(object),如果它是Core-Foundation对象.
如果它的名称中没有这些单词之一,那么该对象属于其他人.[object retain]如果您希望在功能结束后保留对象,则必须调用.
您可以在自己创建的函数中遵循此约定.
(Nitpickers:是的,不幸的是有一些API调用是这些规则的例外,但它们很少见).
如果您正在为桌面编写代码并且可以定位Mac OS X 10.5,那么至少应该考虑使用Objective-C垃圾回收.它真的会简化你的大部分开发 - 这就是为什么Apple会把所有的努力放在首先创建它,并使它表现良好.
至于不使用GC时的内存管理规则:
+alloc/+allocWithZone:,或+new,-copy或者对象创建新对象,-mutableCopy则表示您-retain拥有该对象,并且必须确保将其发送-release.-release.-release您可以自己发送,也可以发送对象-autorelease,当池耗尽时,当前自动释放池将发送它-release(每次收到一次-autorelease).通常-autorelease用作确保对象在当前事件的长度内生存的方式,但之后会被清理,因为有一个自动释放池围绕Cocoa的事件处理.在可可,它是远远更常见的对象返回到被自动释放比它返回调用者本身需要释放OBJETS呼叫者.
Objective-C使用引用计数,这意味着每个Object都有一个引用计数.创建对象时,它的引用计数为"1".简单地说,当一个对象被引用(即存储在某个地方)时,它被"保留",这意味着它的引用计数增加了一个.当不再需要一个对象时,它被"释放",这意味着它的引用计数减少了一个.
当对象的引用计数为0时,将释放该对象.这是基本的参考计数.
对于某些语言,引用会自动增加和减少,但objective-c不是这些语言之一.因此程序员负责保留和释放.
编写方法的典型方法是:
id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;
Run Code Online (Sandbox Code Playgroud)
需要记住在代码中释放任何获取的资源的问题既繁琐又容易出错.Objective-C引入了另一个旨在使这更容易的概念:Autorelease Pools.自动释放池是安装在每个线程上的特殊对象.如果你查找NSAutoreleasePool,它们是一个相当简单的类.
当一个对象发送一个"autorelease"消息时,该对象将查找当前线程的堆栈上的任何自动释放池.它会将对象添加到列表中作为对象,以便在将来的某个时刻发送"释放"消息,这通常是在池本身被释放时.
使用上面的代码,您可以通过以下方式将其重写为更短且更易于阅读:
id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;
Run Code Online (Sandbox Code Playgroud)
因为该对象是自动释放的,所以我们不再需要在其上显式调用"release".这是因为我们知道一些自动释放池将在以后为我们做.
希望这会有所帮助.维基百科的文章非常适合引用计数.有关自动释放池的更多信息,请访问此处.另请注意,如果您正在为Mac OS X 10.5及更高版本构建,则可以告诉Xcode在启用垃圾收集的情况下进行构建,从而允许您完全忽略retain/release/autorelease.
约书亚(#6591) - Mac OS X 10.5中的垃圾收集看起来很酷,但不适用于iPhone(或者如果你希望你的应用程序在10.5之前版本的Mac OS X上运行).
此外,如果您正在编写库或可能重用的内容,使用GC模式会将使用该代码的任何人锁定到也使用GC模式,因此据我了解,任何试图编写广泛可重用代码的人都倾向于管理手动记忆.
我不会添加保留/释放的具体内容,除了你可能想要降低50美元并获得Hillegass书籍,但我强烈建议在应用程序开发的早期阶段开始使用Instruments工具(甚至是你的第一!).为此,请运行 - >使用性能工具.我从泄漏开始,这只是许多可用仪器中的一种,但是当你忘记发布时会有助于告诉你.这是令人畏惧的,你将获得多少信息.但请查看本教程以快速起步:
COCOA TUTORIAL:使用仪器修复内存泄漏
实际上,试图强制泄漏可能是一种更好的方法,反过来,学习如何防止它们!祝好运 ;)
return [[s autorelease] release];
自动释放并没有挽留的对象.自动释放只是将其放入队列中以便稍后释放.你不想在那里有发布声明.
| 归档时间: |
|
| 查看次数: |
32721 次 |
| 最近记录: |