2

我刚刚熟悉了 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 版本。

有什么想法吗?'

4

3 回答 3

6

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

基本上,如果你只写:

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

左侧self.locationManager设置器保留对已分配的引用CLLocationManager。但是右侧的CLLocationManager引用本身永远不会被释放。这个管理器的保留计数永远不会达到零,并且对象永远不会消失——这会导致内存泄漏。

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

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

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

Apple 的Objective-C 编程语言文档更详细地解释了这个属性。

于 2010-04-30T09:31:38.573 回答
1

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

locationManager = [[CLLocationManager alloc] init];

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

如果它是一个类变量(它是),你可以进行赋值。这是否是良好的编码实践值得商榷,但在我看来,这取决于它在课堂开始时的位置。

于 2010-05-06T17:17:53.663 回答
0

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

于 2010-04-30T09:34:34.153 回答