ARC从方法最佳实践返回对象(获取内存泄漏警告)

时间:2021-02-02 21:18:52

I was creating a sample project in xcode 4.2 and noticed that the new project was setup with ARC.

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

I have a method shown below. Previously, I would have autoreleased the cell in the method and let the caller's table view retain the cell. With ARC, autoreleasing would not be possible,

我有一个如下所示的方法。以前,我会在方法中自动释放单元格,让调用者的表视图保留单元格。使用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;
}

When I running the analyze tool on the code above, it says that there is a potential memory leak of the object 'cell'.

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

How should the above be written using ARC so that the analyze warning will go away? What am I doing wrong?

如何使用ARC编写以上内容,以便分析警告消失?我究竟做错了什么?

Thanks.

2 个解决方案

#1


4  

Your method getCellForIndex: allocates and returns an object, in this way it is similar to a straight alloc (indeed your code is just an alloc with some initialization).

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

As ARC does not see the actual implementation of a method when calling it must make an assumption about ownership of the returned object, and that assumption is that ownership is not transferred. When compiling your implementation ARC notices that your code violates this assumption and warns you.

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

The assumption can be overridden by adding an explicit attribute to your method in both the @interface and @implementation:

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

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

ARC will now know the object ownership is transferred. Methods in the alloc, new etc. families have this attribute added automatically. As other replies suggest you might be better off renaming your method, newCellForIndex: might be appropriate here as new is used for a combination of alloc and init which is what your method does.

ARC现在知道对象所有权已转移。 alloc,new等系列中的方法会自动添加此属性。正如其他回复建议你最好重命名你的方法一样,newCellForIndex:在这里可能是合适的,因为new用于alloc和init的组合,这是你的方法所做的。

BTW: Changing your second & third if's to else if's would make your algorithm clearer (and slightly faster, but that is not the reason to do it).

BTW:改变你的第二个和第三个if if to else if会使你的算法更清晰(并且稍快一点,但这不是理由)。

Question in comment:

评论中的问题:

ARC does introduce new attributes etc. but also uses inference and defaults so that if you follow normal Cocoa conventions you shouldn't need them too often - YMMV of course... In addition to Apple's docs you can find a description here.

ARC确实引入了新的属性等,但也使用推理和默认值,这样如果你遵循正常的Cocoa约定,你就不应该经常使用它们 - 当然YMMV ......除了Apple的文档,你可以在这里找到描述。

#2


5  

Try renaming the method to -cellForIndex:, "get"-prefixed methods have different implied behavior in Cocoa.

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

(Also, maybe -cellAtIndex: for consistency with NSArray, etc...)

(另外,也许-cellAtIndex:为了与NSArray等一致......)

#1


4  

Your method getCellForIndex: allocates and returns an object, in this way it is similar to a straight alloc (indeed your code is just an alloc with some initialization).

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

As ARC does not see the actual implementation of a method when calling it must make an assumption about ownership of the returned object, and that assumption is that ownership is not transferred. When compiling your implementation ARC notices that your code violates this assumption and warns you.

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

The assumption can be overridden by adding an explicit attribute to your method in both the @interface and @implementation:

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

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

ARC will now know the object ownership is transferred. Methods in the alloc, new etc. families have this attribute added automatically. As other replies suggest you might be better off renaming your method, newCellForIndex: might be appropriate here as new is used for a combination of alloc and init which is what your method does.

ARC现在知道对象所有权已转移。 alloc,new等系列中的方法会自动添加此属性。正如其他回复建议你最好重命名你的方法一样,newCellForIndex:在这里可能是合适的,因为new用于alloc和init的组合,这是你的方法所做的。

BTW: Changing your second & third if's to else if's would make your algorithm clearer (and slightly faster, but that is not the reason to do it).

BTW:改变你的第二个和第三个if if to else if会使你的算法更清晰(并且稍快一点,但这不是理由)。

Question in comment:

评论中的问题:

ARC does introduce new attributes etc. but also uses inference and defaults so that if you follow normal Cocoa conventions you shouldn't need them too often - YMMV of course... In addition to Apple's docs you can find a description here.

ARC确实引入了新的属性等,但也使用推理和默认值,这样如果你遵循正常的Cocoa约定,你就不应该经常使用它们 - 当然YMMV ......除了Apple的文档,你可以在这里找到描述。

#2


5  

Try renaming the method to -cellForIndex:, "get"-prefixed methods have different implied behavior in Cocoa.

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

(Also, maybe -cellAtIndex: for consistency with NSArray, etc...)

(另外,也许-cellAtIndex:为了与NSArray等一致......)