我刚刚开始了解 Objective-C 和 Cocoa,以便使用 iPhone SDK。我对 C 的 malloc
和 free
概念相当满意,但 Cocoa 的引用计数方案让我很困惑。有人告诉我,一旦你理解它就非常优雅,但我还没有完成。
release
、retain
和 autorelease
是如何工作的,它们的使用约定是什么?
(或者失败了,你读了什么帮助你得到它?)
最佳答案
让我们从retain
和release
开始; autorelease
只是你了解基本概念后的一个特例。
在 Cocoa 中,每个对象都会跟踪它被引用的次数(具体来说,NSObject
基类实现了这一点)。通过在一个对象上调用 retain
,你是在告诉它你想将它的引用计数加一。通过调用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
现在是 autorelease
。自动释放被用作一种方便(有时是必要的)方法来告诉系统在一段时间后释放这个对象。从管道的角度来看,当调用 autorelease
时,当前线程的 NSAutoreleasePool
会收到调用警报。 NSAutoreleasePool
现在知道一旦它获得机会(在事件循环的当前迭代之后),它可以在对象上调用 release
。从我们作为程序员的角度来看,它负责为我们调用 release
,所以我们不必(事实上,我们不应该)。
需要注意的重要一点是(同样,按照惯例)所有对象创建 class 方法都会返回一个自动释放的对象。例如,在下面的例子中,变量“s”的引用计数为 1,但在事件循环完成后,它将被销毁。
NSString* s = [NSString stringWithString:@"Hello World"];
如果你想卡在那个字符串上,你需要显式调用 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];
}
我意识到这一切有点令人困惑——不过,在某些时候,它会点击。这里有一些引用资料可以帮助您:
https://stackoverflow.com/questions/6578/
相关文章:
iphone - SplitView 就像 iPhone 上的 Facebook 应用程序
objective-c - 为什么 Objective-C 不支持私有(private)方法?
objective-c - 在框架模块中包含非模块化 header
objective-c - 如何在 iPhone 模拟器中更改时间和时区?
objective-c - NSPredicate:按 NSDate 属性的日期过滤对象
iphone - 检测导航栏上的 'back' 按钮何时被按下
iphone - Storyboard - 引用 AppDelegate 中的 ViewContro
iphone - -all_load 链接器标志有什么作用?