我想知道在内存托管代码中,对象不属于任何特定所有者,即自己发布的对象的情况,建议使用哪些方法。一个这样的例子可以是NSWindowController的子类,它配置,显示和管理单个窗口的输入和输出。控制器对象显示一个窗口,稍后在某个时刻释放(通常在它管理的窗口或工作表关闭时)。 AppKit也提供了几个例子:NSAnimation在startAnimation中保留自己,并在动画完成时自行释放。另一个例子是NSWindow,可以配置为在关闭时释放自己。
当我自己实现这些“自有”对象时,我看到至少三种不同的GC安全模式,但它们都有一些缺点。
A)。使用CFRetain / CFRelease。
自有对象在开始运行之前调用CFRetain(例如在显示窗口之前的窗口控制器示例中)。然后它在完成时调用自己的CFRelease()(例如在窗口关闭后的窗口控制器示例中)。
优点:对象的用户不必担心内存管理 缺点:有点难看,因为需要使用内存管理功能,尽管我们在纯ObjC代码中使用GC。如果没有调用CFRelease(),可能很难找到泄漏。
B)。使用静态数据结构避免自我所有权习惯。
Object在开始运行之前将自身添加到数据结构(例如静态可变数组)中,并在完成时将其自身移除。
优点:对象的用户不必担心内存管理。没有调用内存管理功能。对象有明确的所有者。潜在的泄漏很容易找到。
缺点:如果可以从不同的线程创建对象,则需要锁定。额外的数据结构。
C)。通过要求对象的用户保存对象的引用(例如,进入ivar)来避免自我拥有成语。
优点:没有调用内存管理功能。对象有明确的所有者 缺点:即使对象不再需要该对象,该对象的用户也必须保留引用。额外的伊娃。
你会用什么模式处理这些案件?
答案 0 :(得分:5)
对于a),CFRetain(foo)
/ CFRelease(foo)
的惯用替代方案是[[NSGarbageCollector defaultCollector] disableCollectorForPointer:foo]
/ [[NSGarbageCollector defaultCollector] enableCollectorForPointer:foo]
。
答案 1 :(得分:2)
Apple的建议是(c),但我喜欢(b)的声音。静态数据结构允许您隐藏API用户的GC详细信息,同时避免浸入CFRetain / CFRelease级别。正如您所说,它还使调试和单元测试更容易;如果静态数据结构在完成任务后仍然引用了一个对象,那么就知道存在错误。