为什么我应该在我的setter方法中将-autorelease发送到我的实例变量,而不是-release?

时间:2009-04-26 11:05:43

标签: iphone objective-c cocoa-touch memory-management

Apple在实例变量mainSprocket:

的setter方法中执行此操作
– (void)setMainSprocket:(Sprocket *)newSprocket {
    [mainSprocket autorelease];
    mainSprocket = [newSprocket retain];
    return;
}

为什么他们发送-autorelease而不是-release?这是一个不好的效果吗?实际上它不应该(因为我的理解),因为-release只是说实例变量mainSprocket持有的当前对象不再被该实例变量使用。对于其他人仍然对该对象仍然感兴趣的情况,该方法可以保留它,对吧?那么 - 发布应该没事,我想?

2 个答案:

答案 0 :(得分:4)

如果mainSprocketnewSprocket是同一个对象,那么如果您使用简单的release,它就会被释放。

如果您不想使用autorelease,请使用:

– (void)setMainSprocket:(Sprocket *)newSprocket {
    // if newSprocket and mainSprocket were the same object, 
    // it would first be retained and then released
    // and therefore not deleted.
    [newSprocket retain];
    [mainSprocket release];
    mainSprocket = newSprocket;
    // you don't need return in a void-method
    // return;
}

你为什么不使用房产?它们是Objective-C 2.0的实现方式。

<强> SomeObject.h

@interface SomeObject : NSObject {
    Sprocket *mainSprocket;
}

@property(retain) Sprocket *mainSprocket;

@end

<强> SomeObject.m

@implementation SomeObject

@synthesize mainSprocket;

@end

答案 1 :(得分:3)

如果autoreleasenewSprocket碰巧是同一个对象,他们会在mainSprocket进行此操作。调用release可能会无意中释放对象,然后才能将其保留在下一行,而autorelease将不会被处理,直到自动释放池在事件循环结束时耗尽。< / p>

考虑这种情况:

Sprocket *mySprocket = [Sprocket spacelySprocket];
[sprocketManager setMainSprocket:mySprocket];

Sprocket *anotherPointerToMySprocket = mySprocket;
[sprocketManager setMainSprocket:anotherPointerToMySprocket];

如果mainSprocket未自动释放,则最后一行会导致问题。您可能有时会看到执行相同操作的setter代码的另一个约定是:

– (void)setMainSprocket:(Sprocket *)newSprocket {
    if (newSprocket != mainSprocket) {
        [mainSprocket release];
        mainSprocket = [newSprocket retain];
    }
}

我会让其他人评论哪个更合适或更美观: - )