嗯,我仍然对目标c属性和实例变量感到困惑。我在视图DidLoad中创建了一个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;
除了第二个有效和第一个无效之外,这些例子之间有什么区别?内存管理是怎么回事?
您在第一个示例中遇到的问题:
CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];
由CCD_ 1的使用引起。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,并且不会释放该对象。
你必须清楚地知道:
CCD_ 7将保留计数设置为1;
retain
属性在分配给它们时将增加保留计数;autorelease
就像一个延迟发布,因此在发布之前,也就是说在方法和调用程序的其余部分直到主循环中,您可以安全地使用该对象,然后它就会被释放。
我在代码中标记了保留的更改,也许它会变得更清楚。
CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];
^^^^^ + 1 ^^^^^^^^^^^ - 1 = 0
_locationMan = theManager;
当您的retains drop为0时,该对象就不存在了。下次你尝试访问它时,你的应用程序会崩溃。由于自动释放,这将在您的自动释放池耗尽后发生,在您离开当前方法后的未来未知点。
self.locationMan = [[[CLLocationManager alloc] init] autorelease];
^ + 1 ^^^^^ + 1 ^^^^^^^^^^^ - 1 = +1
您仍然保留了该对象。你必须稍后发布它,但你可以毫无问题地访问它。
在第一个实例中,您没有经过合成的setter,它负责保留对象。在这种情况下,当autorelease
0被自动释放时,_locationManager
没有抓住任何东西,因此theManager
被解除锁定。
第二种情况使用合成的setter(因为它通过self
调用它),所以它在自动释放后保留theManager
。