我只是熟悉了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版本。
有什么想法? “
答案 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(因为保留属性)。您可以在将其设置为属性后显式释放它,但您所做的是代码更少且易于阅读。