我对Objective-C还很陌生,所以这可能是一个愚蠢的问题。我不禁注意到ObjC和Microsoft的COM在内存管理方面有相似之处(AddRef/Release与retain/release)。在COM环境中,你几乎总是被强制在将对象返回给调用者之前添加AddRef(retain)。到目前为止,从我所见的(我已经阅读了《Cocoa® Programming for Mac® OS X (第三版)》的三分之一),内存管理部分有些模糊。假设没有GC,那么返回一个对象的惯用方式是什么?
阅读 内存管理编程指南 了解自动释放池。
在 Objective-C 中,按照惯例,除非返回对象的方法名以“alloc”、“new”、“copy”或“mutableCopy”开头,否则应该返回自动释放的对象。自动释放的对象由 Objective-C 在一个池中跟踪并自动处理,这意味着你不需要关心向它们发送最终释放的操作。与 COM 相比,这极大地简化了引用计数,因此你大部分时间都看不到返回对象的 release
调用。相反,同样的惯例指定了所有由名称以 alloc、new、copy 或 mutableCopy 开头的方法返回的对象是方法调用者的责任。你必须手动对这些对象调用 release,否则你的程序将会有内存泄漏问题。
Cocoa通过引入第三个兄弟姐妹autorelease
,绕过了COM中AddRef
/Release
方法的限制。
retain
- 我需要这个,让它留下来。release
- 我不再需要这个,你可以立即删除它。autorelease
- 我不需要这个,但还是让它保留几秒钟,以便其他人先捡起来。这个小小的补充使得大多数返回值可以被处理,就像我们拥有垃圾回收一样。如果你不想保留返回值,就无需额外操作。
为了让这个功能正常工作,有一个约定(一个足够好的约定,可以让编译器自动处理内存,使用即将推出的ARC):
alloc
copy
new
retain
以下是三个示例实现,展示了如何将其应用于实际情况:
-(NSString*)newHelloWorldString {
NSString* s = [NSString stringWithString:@"Hello world"];
// Apply retain because s in now autoreleased
return [s retain];
}
-(NSString*)helloWorldString {
NSString* s = [[NSString alloc] initWithString:@"Hello world"];
// Apply autorelease because s is now retained.
return [s autorelease];
}
-(NSString*)fullName {
// No memory management needed, everything is autoreleased and good.
NSString* fn = [self firstName];
NSString* ln = [self lastName];
NSString* s = [NSString stringWithFormat:@"%@ %@", fn, ln];
return s;
}
return [object autorelease];
,因为我很少会像这样构建代码结构。不要仅仅盲目地在返回值上打上自动释放标记;请阅读内存管理指南并理解您正在做的事情。 - kubi我建议让接收它的类保留它。即,类stackoverflow接收对象answer。
i.e
-(void) setAnswer:(Answer*) _answer{
self.answer = _answer; // If the answer is created from a returned message.
[_answer release];
}
编辑:我想我可能在第二次查看时放错了东西。我的意思是类似于:
Answer *_answer = [stackoverflow createAnswer];
self.answer = _answer;
[_answer release];
如果你返回一个对象,它的保留由所有者负责,我会尽可能避免使用自动释放,因为一旦 nspool 启动,这些对象就会消失,如果它们仍在使用中,将会引起问题。
例如:Answer *answer = [stackoverflow getAnswer],如果 answer 是在 getanswer 方法中创建的,那么检索它的人负责释放它。
有道理吗?
return [objectName autorelease];
。在这样做之前,请确保您没有将autorelease
发送到已经在其他地方被自动释放的对象上并返回它。如果这样做,很可能会导致您的应用程序随机崩溃。至少这是我的经验。 - RobK