为什么在使用setter将自定义对象分配给实例变量时使用自动释放?

时间:2021-03-18 09:37:56

I want to assign a custom object to an instance variable.

我想将自定义对象分配给实例变量。

Here is the code:
- MyController.h/.m

这是代码: - MyController.h / .m

#import "CustomData.h"  
@interface MyViewController : NSViewController  
@property (retain) CustomData* theData;  

- (void)aRandomMethod; 

@end

@implementation MyViewController  
@synthetize theData;  

- (void)aRandomMethod {  

   NSData* rawData = [someOtherObject someOtherMethod];

   // option 1
   self.theData = [[CustomData alloc] initWithData:rawData];

   // option 2
   CustomData* _theData = [[Custom alloc] initWithData:rawData];

   // option 3
   self.theData = [[[CustomData alloc] initWithData:rawData] autorelease];

   // option 4
   theData = [[CustomData alloc] initWithData:rawData];

   // ... later code calls some methods on theData or _theData, not useful here.
 }
@end

When running the Analyze feature in Xcode, it tells me that there is a "leaked object not referenced later..." for option 1 and 2, but not for 3 and 4. It seems that I need to autorelease the custom object when using the setter. I know that autoreleaseneeds to be used when returning an object we own in a method.

在Xcode中运行Analyze功能时,它告诉我有一个“泄漏的对象,以后没有引用...”,对于选项1和2,但不是3和4.看来我需要在使用时自动释放自定义对象二传手。我知道在返回我们在方法中拥有的对象时需要使用autorelease。

Could you explain for each option why is it wrong or right ? Thanks.

你能解释一下每个选项为什么是错的还是对的?谢谢。

2 个解决方案

#1


5  

Option 1 is wrong, because you alloc'd the object in that method, so that method now owns the object, and therefore needs to release it. When you assign it to a property, that retains it and is expected to release it when it's done with it.

选项1是错误的,因为您在该方法中分配了对象,因此该方法现在拥有该对象,因此需要释放它。当您将其分配给某个属性时,它会保留该属性,并且在完成后会释放它。

Option 2 is wrong for the same reason. You take out the property part of it, but because you created the object with alloc, you're responsible for calling release on it in that method.

出于同样的原因,选项2是错误的。你取出它的属性部分,但因为你用alloc创建了对象,你负责在该方法中调用它的释放。

Option 3 is correct, because you've autoreleased it before giving it to the property, so the method no longer owns it. Note that if you used release here it would break, because it would release it before the property gets a chance to retain it.

选项3是正确的,因为您在将其提供给属性之前已经自动释放它,因此该方法不再拥有它。请注意,如果您在此使用release,它将会中断,因为它会在属性有机会保留之前释放它。

Option 4 could be correct; I'm assuming it's assigning it to an ivar. It's only correct if you're later manually releasing the ivar in your dealloc method. It's generally better to go through properties though. Otherwise you run the risk of assigning another value and forgetting to release the existing value.

备选方案4可能是正确的;我假设它正在将它分配给ivar。如果您稍后在dealloc方法中手动释放ivar,那么这是正确的。通过房产通常会更好。否则,您将面临分配其他值并忘记释放现有值的风险。

#2


1  

The biggest thing to note for options 1 and 2 is that there is an alloc, and thus needs to be a corresponding release.

选项1和2最值得注意的是有一个alloc,因此需要是相应的版本。

Option 1 is, in essence, "hidden", because the compiler auto-generates setters and getters for you. What you don't see is that, when using dot notation, you are going through the setter, which implicitly includes a retain call. Thus you are allocating the object AND retaining, giving it a retain count of 2.

选项1本质上是“隐藏的”,因为编译器会自动为您生成setter和getter。您没有看到的是,当使用点表示法时,您将通过setter,它隐含地包含一个保留调用。因此,您将分配对象AND retain,使其保留计数为2。

Therefore, in order to make sure it is able to be properly released in the future, you must designate it to be added to an autorelease pool for the system to clean up later. This will bring the retain count to 1, and in your dealloc method you can then safely release the property.

因此,为了确保将来能够正确发布,您必须将其指定为添加到自动释放池中,以便系统稍后进行清理。这将使保留计数为1,然后在您的dealloc方法中,您可以安全地释放该属性。

#1


5  

Option 1 is wrong, because you alloc'd the object in that method, so that method now owns the object, and therefore needs to release it. When you assign it to a property, that retains it and is expected to release it when it's done with it.

选项1是错误的,因为您在该方法中分配了对象,因此该方法现在拥有该对象,因此需要释放它。当您将其分配给某个属性时,它会保留该属性,并且在完成后会释放它。

Option 2 is wrong for the same reason. You take out the property part of it, but because you created the object with alloc, you're responsible for calling release on it in that method.

出于同样的原因,选项2是错误的。你取出它的属性部分,但因为你用alloc创建了对象,你负责在该方法中调用它的释放。

Option 3 is correct, because you've autoreleased it before giving it to the property, so the method no longer owns it. Note that if you used release here it would break, because it would release it before the property gets a chance to retain it.

选项3是正确的,因为您在将其提供给属性之前已经自动释放它,因此该方法不再拥有它。请注意,如果您在此使用release,它将会中断,因为它会在属性有机会保留之前释放它。

Option 4 could be correct; I'm assuming it's assigning it to an ivar. It's only correct if you're later manually releasing the ivar in your dealloc method. It's generally better to go through properties though. Otherwise you run the risk of assigning another value and forgetting to release the existing value.

备选方案4可能是正确的;我假设它正在将它分配给ivar。如果您稍后在dealloc方法中手动释放ivar,那么这是正确的。通过房产通常会更好。否则,您将面临分配其他值并忘记释放现有值的风险。

#2


1  

The biggest thing to note for options 1 and 2 is that there is an alloc, and thus needs to be a corresponding release.

选项1和2最值得注意的是有一个alloc,因此需要是相应的版本。

Option 1 is, in essence, "hidden", because the compiler auto-generates setters and getters for you. What you don't see is that, when using dot notation, you are going through the setter, which implicitly includes a retain call. Thus you are allocating the object AND retaining, giving it a retain count of 2.

选项1本质上是“隐藏的”,因为编译器会自动为您生成setter和getter。您没有看到的是,当使用点表示法时,您将通过setter,它隐含地包含一个保留调用。因此,您将分配对象AND retain,使其保留计数为2。

Therefore, in order to make sure it is able to be properly released in the future, you must designate it to be added to an autorelease pool for the system to clean up later. This will bring the retain count to 1, and in your dealloc method you can then safely release the property.

因此,为了确保将来能够正确发布,您必须将其指定为添加到自动释放池中,以便系统稍后进行清理。这将使保留计数为1,然后在您的dealloc方法中,您可以安全地释放该属性。