【问题标题】:ARC returning object from method best practice (getting memory leak warning)ARC 从方法最佳实践返回对象(获取内存泄漏警告)
【发布时间】:2026-01-31 02:55:01
【问题描述】:

我在 xcode 4.2 中创建了一个示例项目,并注意到新项目是使用 ARC 设置的。

我有一个如下所示的方法。以前,我会在方法中自动释放单元格并让调用者的表格视图保留该单元格。使用 ARC,将无法自动发布,

- (UITableViewCell*) getCellForIndex:(int)index {

    UITableViewCell *cell =         
        [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];

    if (index == 0)
        cell.textLabel.text = profileToUse.name;
    if (index == 1)
        cell.textLabel.text = profileToUse.sex;
    if (index == 2)
        cell.textLabel.text = profileToUse.city;
    return cell;
}

当我在上面的代码上运行分析工具时,它说对象'cell'存在潜在的内存泄漏。

上面应该如何使用 ARC 编写,以便分析警告消失?我做错了什么?

谢谢。

【问题讨论】:

    标签: objective-c automatic-ref-counting


    【解决方案1】:

    您的方法getCellForIndex: 分配并返回一个对象,这样它类似于直接的alloc(实际上您的代码只是一个带有一些初始化的alloc)。

    由于 ARC 在调用它时看不到方法的实际实现,因此必须对返回的对象的所有权做出假设,并且该假设是所有权转移。在编译你的实现时,ARC 注意到你的代码违反了这个假设并警告你。

    可以通过在@interface@implementation 中向您的方法添加显式属性来覆盖该假设:

    - (UITableViewCell*) getCellForIndex:(int)index __attribute((ns_returns_retained))
    

    ARC 现在将知道对象所有权已转移。 allocnew 等系列中的方法会自动添加此属性。正如其他回复所暗示的那样,您最好重命名您的方法,newCellForIndex: 在这里可能是合适的,因为 new 用于 allocinit 的组合,这就是您的方法所做的。

    顺便说一句:将您的第二个和第三个 if 更改为 else if 将使您的算法更清晰(并且速度稍快,但这不是这样做的原因)。

    评论中的问题:

    ARC 确实引入了新属性等,但也使用推理和默认值,因此如果您遵循正常的 Cocoa 约定,您不应该经常需要它们 - 当然是 YMMV...除了 Apple 的文档之外,您还可以找到描述 @ 987654321@.

    【讨论】:

    • 这个例子是我拥有的 cellcreator 类的简化版本。我必须动态添加不同的单元格类型(标签+tetfield、标签+标签(用于 datepicker 调用)并在几个地方执行此操作,因此需要一个类在一个地方执行此操作。
    • 哇!!!。做到了。谢谢。因此,要使用 ARC,需要了解一组全新的属性和标签,并通过声明明确其意图。与手动管理内存相比,这实际上加快了开发速度吗?是否有这些属性的列表?
    • 我评论了该属性,将方法重命名为“newCellAtIndex”,甚至消除了警告。所以命名也可以解决它。
    【解决方案2】:

    尝试将方法重命名为 -cellForIndex:,以“get”为前缀的方法在 Cocoa 中具有不同的隐含行为。

    (另外,可能是-cellAtIndex:为了与NSArray等保持一致……)

    【讨论】:

    • 具体来说,以“get”为前缀的方法应该接受一个指针参数并通过引用返回一个值。以 NSArray 的- (void)getObjects:(id *)aBuffer range:(NSRange)aRange 为例。我不确定这实际上是否会导致警告。至少我无法重现它......
    • 是的。只有当你的方法遵循 Cocoa 约定时,ARC 才能工作。
    • catfist_man。在使用 CRD 的方法名称建议后:'newCellAtIndex' 警告消失了。所以你在精神上是对的。只是将其命名为“cellAtIndex”并没有使警告消失。谢谢!!!
    • 我见过 new 和 create 在 Apple 的框架中使用,例如newCellForIndex 当方法与返回的对象在不同的​​类中时。