为什么在init方法中为iVar定义调用autorelease?

时间:2010-04-30 09:22:19

标签: iphone objective-c xcode core-location cllocationmanager

我只是熟悉了CLLocationManager,发现了几个包含以下init方法的示例类定义:

- (id) init {
    self = [super init];

    if (self != nil) {
        self.locationManager = [[[CLLocationManager alloc] init] autorelease];
        self.locationManager.delegate = self;
    }
    return self;
}

- (void)dealloc {
    [self.locationManager release];
    [super dealloc];
}

我不明白为什么iVar会被自动释放。这是否意味着它在init方法结束时被解除分配?

我也很困惑地​​看到相同的示例代码在dealloc方法中有iVar版本。

有什么想法? “

3 个答案:

答案 0 :(得分:6)

locationManager是可能使用retain属性设置的属性。

基本上,如果你只写:

self.locationManager = [[CLLocationManager alloc] init];

左侧self.locationManager setter保留对分配的CLLocationManager的引用。但右侧CLLocationManager引用本身从未发布过。该经理的保留计数永远不会达到零,对象永远不会消失 - 这会导致内存泄漏。

有两种方法可以解决这个问题。您在引用的代码段中看到的autorelease已分配的对象 - 或者您将已分配的对象分配给临时变量,将临时变量保留到locationManager属性,然后显式释放临时变量:

CLLocationManager *_temporaryReference = [[CLLocationManager alloc] init];
self.locationManager = _temporaryReference; // this is retained
[_temporaryReference release];

就内存管理而言,这两种方法都是等效的。有些人更喜欢第二种方法,因为他们不喜欢等待自动释放池被“清空”,尤其是在像iPhone这样的低内存设备上,这样可以更严格地控​​制对象的生命周期。

Apple的Objective-C Programming Language文档更详细地解释了这个属性。

答案 1 :(得分:1)

有一种没有临时变量或自动释放的替代方法:

locationManager = [[CLLocationManager alloc] init];

如果不使用self.locationManager,则不会为该变量调用类的setter方法,因此不会将保留计数增加到2.编译器会将这些赋值更改为[self setLocationManager: locationManager];。这假定您已将变量原型化为保留。

如果它是一个类变量(它是),你可以只进行赋值。这是否是良好的编码实践是有争议的,但在我看来,这取决于它在课堂启动中的位置。

答案 2 :(得分:0)

如果你的self.locationManager是一个保留它的属性,那么它会设置retain。通过执行alloc,您可以将retain count设置为+1,这意味着在函数结束时它是+2。当你说autorelease时,它将是+1(因为保留属性)。您可以在将其设置为属性后显式释放它,但您所做的是代码更少且易于阅读。