Iphone - 分配属性和实例变量

时间:2011-06-02 12:19:14

标签: iphone memory properties instance-variables

好吧,我仍然对目标c属性和实例变量感到困惑。 我在viewDidLoad中创建了一个LocationManager对象。一方面,LocationMan只是一个实例变量,另一方面它被声明为属性。看看这些例子:

第一个例子:

部首:

CLLocationManager* _locationMan;

实现:

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];
_locationMan = theManager;
_locationMan.delegate = self;

第二个例子

部首:

CLLocationManager* _locationMan;
@property (retain, nonatomic) CLLocationManager* locationMan;

实现:

self.locationMan = [[[CLLocationManager alloc] init] autorelease];
self.locationMan.delegate = self;

这些例子之间的区别是什么,除了第二个是工作而第一个没有?内存管理会发生什么?

3 个答案:

答案 0 :(得分:3)

您在第一个示例中遇到的问题:

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];

是由使用autorelease引起的。 autorelease可以被视为含义:在不久的将来的某个时刻,release会自动显示此对象。给定autorelease的实现方式,通过发布池,这通常在下一次控制流返回主循环并且释放池被清空时发生。

因此,在您的第一种情况下,您正在创建对象并将其存储在您的ivar中;但很快它就会被释放,而且由于你没有在其他任何地方明确地保留它,它最终会被释放。之后访问它时,会出现错误。如果你没有使用autorelease,一切都会正常工作:

CLLocationManager* theManager = [[CLLocationManager alloc] init]; //-- this is correct
_locationMan = theManager;  //-- because you assign directly to the ivar

在你的第二个例子中,创建是一样的,这意味着,对象也将被标记为自动释放。但是,在这种情况下,您将其分配给具有retain修饰符的属性。这意味着在分配属性时将自动保留对象。因此,当自动释放实际完成时(粗略地回到主要外观),您的对象已经将其保留计数递增1;然后自动释放它不会使其保留计数变为0,并且该对象将不会被释放。

你必须清楚知道的是:

  1. alloc会将保留计数设置为1;

  2. retain属性会在分配时增加保留计数;

  3. autorelease就像一个延迟发布,所以在同一时间(在发布实际完成之前,这意味着在你的方法的其余部分和调用者到主循环之前)你可以使用对象安全,然后将被释放。

答案 1 :(得分:1)

我在代码中标记了保留的更改,可能会更清晰。

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];
                                                     ^^^^^ + 1    ^^^^^^^^^^^ - 1 = 0
_locationMan = theManager;

当您的保留值降至0时,该对象不再存在。下次您尝试访问它时,您的应用程序崩溃。由于自动释放,这将在您的自动释放池耗尽后,在您离开当前方法后的未来未知点发生。


self.locationMan = [[[CLLocationManager alloc] init] autorelease];
    ^ + 1                               ^^^^^ + 1    ^^^^^^^^^^^ - 1 = +1

您仍然保留该对象。你必须稍后发布它,但你可以毫无问题地访问它。

答案 2 :(得分:0)

在第一个实例中,您没有经过合成的setter,它负责保留对象。在这种情况下,当theManager被自动释放时,_locationManager不会保留任何内容,因此theManager会被取消分配。

第二种情况使用合成的setter(因为它通过self调用它),因此它在自动释放后保留theManager