我正在使用-initWithObjectsAndKeys创建一个NSDictionary:。
对于我提供给该字典的每个对象,我调用一个自制方法-createFooBarObject,它将创建并返回该对象。
现在问题:按定义创建方法不应该释放对象,因为它必须返回它,并且调用者负责释放它。但是在这里,调用者没有机会释放它,因为NSDictionary立即吸收它。我在-initWithObjectsAndKeys:对象和键列表中调用了create-method,所以在添加到字典后我没有机会调用-release。好吧,我可以迭代字典并释放它们。但那很难看。
在-createFooBarObject方法中返回之前,它是否对-autorelease有效?我不确定将在何时发生自动发布。但它不应该在字典创建并保留该对象之前发生。有什么想法吗?
答案 0 :(得分:3)
如果您正在调用+ alloc来创建对象(您看起来像是),那么您必须释放或自动释放。
如果创建一个返回使用+ alloc创建的对象的方法,则必须返回一个自动释放的对象。
另一种方法是不做设计模式所说的事情,然后处理你的不同模式和阻抗不匹配。除非性能分析表明您的性能问题只能通过这样做来解决,否则不要去那里。
在这种情况下,您可能希望返回一个自动释放的对象。然后调用者不必担心调用-release或-autorelease。这是应该的。
答案 1 :(得分:2)
对于Objective-C API,“new”表示+1参考返回值。对于CoreFoundation,“创建”确实如此。相反的情况并非如此:“创造”和“新”不可互换。
因此,在Objective-C中,“createFooBarObject”表示根据当前规则自动释放的对象,您应该自动释放它。如果你真的打算返回一个+1引用对象,你应该在名称中使用“new”而不是“create”。
这些规则由clang static analyzer检查。
clang-sa还允许您通过属性((ns_returns_retained))或属性来定义与您的正常约定不同的annotate methods(( cf_returns_retained))。例如,如果ObjC方法通过“create”返回一个新的CF对象(如QuartzCore - [CIContext createCGImage:fromRect:]),则会出现边缘情况。如果您有这样的API,并且clang-sa误解了您的意图,您可以将该方法注释为特定的,即返回具有特定引用类型的对象。
答案 2 :(得分:0)
两个注意事项:您使用alloc创建一个对象,使用initWithObjectsAndKeys初始化它 - alloc / init始终是配对的,因此它通常只是技术差异。
但更重要的是,创建方法应该 NOT 返回一个拥有的对象,你应该自动释放它。这在memory management rules中明确指定。鉴于该规范以及命名方法“create”导致的混淆,我建议永远不要在方法名称中使用“create”,而是将其称为fooBarObject并返回自动释放(或其他无主)对象。如果你这样做,那么你的问题会立即解决。
在-createFooBarObject方法中返回之前,它是否对-autorelease有效?
它不仅有效,而且绝对需要 - 如果您自动释放的对象在此时归您所有(即,您可以合法地调用释放)。
我不确定-autorelease会在哪一点发生。
自动释放池很简单 - 系统保存指向对象的指针的副本,当自动释放池被排空/释放时,它会将释放方法发送给对象。
自动释放池是嵌套的,永远不会被意外地神奇地耗尽 - 当控制流返回给创建自动释放池的人并且他们释放它时,它们将被耗尽通常这是最初调用代码来处理的代码的运行循环事件
但是,即使这种理解在很大程度上是无关紧要的 - 只需阅读memory management rules并遵循这些规则,你就不会有任何问题。