Iphone - 分配属性和实例变量
好吧,我仍然对 Objective 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;
这些示例之间有什么区别,除了第二个示例正常运行之外第一个不是?内存管理到底发生了什么?
Well, i am still confused about objective c properties and instance variables.
I create a LocationManager-object in my viewDidLoad. On the one hand the LocationMan is just an instance variable on the other hand it is declared as a property. Have a look at the examples:
First example:
Header:
CLLocationManager* _locationMan;
Implementation:
CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];
_locationMan = theManager;
_locationMan.delegate = self;
Second Example
Header:
CLLocationManager* _locationMan;
@property (retain, nonatomic) CLLocationManager* locationMan;
Implementation:
self.locationMan = [[[CLLocationManager alloc] init] autorelease];
self.locationMan.delegate = self;
Whats the difference between those examples except of that the second one is working and the first one not? What's going on there with the memory management?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
第一个示例中遇到的问题:
是由使用
autorelease
引起的。autorelease
可以理解为:在不久的将来的某个时刻,release
自动释放这个对象。考虑到通过释放池实现自动释放的方式,这通常会在下次控制流返回主循环并且释放池被清空时发生。因此,在第一种情况下,您正在创建对象并将其存储在 ivar 中;但很快它就会被释放,并且由于您没有在其他地方明确保留它,所以它最终会被释放。当您之后访问它时,您会收到错误。如果您没有使用 autorelease,一切都会正常工作:
在第二个示例中,创建是相同的,这意味着该对象也将被标记为自动释放。但是,在本例中,您将其分配给具有
retain
修饰符的属性。这意味着在分配给属性时该对象将被自动保留。因此,当自动释放实际完成时(粗略地,当您返回主视图时),您的对象的保留计数将已经增加 1;那么自动释放它不会使其保留计数变为0,并且该对象不会被释放。你必须清楚地知道的是:
alloc
会将保留计数设置为 1;retain
属性在分配给它们时将增加保留计数;autorelease
就像延迟释放一样,因此同时(在释放实际完成之前,这意味着在方法的其余部分和主循环之前的调用者中)您可以使用对象安全,然后它将被释放。The problem you have in your first example:
is caused by the use of
autorelease
.autorelease
can be seen as meaning: at some point in the near future,release
automatically this object. Given the wayautorelease
is implemented, by means of a release pool, this usually happens the next time the control flow return to the main loop and the release pool is emptied.So, in your first case, you are creating the object and storing it in your ivar; but soon it will be released, and since you don't have explicitly retained it anywhere else, it will end up being deallocated. When you access it after that, you get the error. If you had not used
autorelease
, everything would have worked correctly:In your second example, creation is just the same, meaning, the object will also be flagged for autorelease. But, in this case, you assign it to a property which has got the
retain
modifier. This means that the object will be automatically retained when assigning to the property. So, when the autorelease is actually done (when you get back to the main look, roughly), your object will have already had its retain count incremented by 1; then auto releasing it will not make its retain count go to 0, and the object will not be deallocated.What you have to know clearly is that:
alloc
will set the retain count to 1;retain
properties will increment the retain count when assigning to them;autorelease
is like a delayed release, so that in the mean time (before the release is actually done, which means in the rest of your method and callers up to the main loop) you can use the object safely and thereafter it will be released.我在你的代码中标记了retains的变化,也许它会变得更清楚。
当你的retains下降到0时,该对象就不再存在了。下次您尝试访问它时,您的应用程序会崩溃。由于自动释放,这种情况会在您的自动释放池耗尽后发生,在您离开当前方法后的未知时刻。
你仍然保留了那个对象。您必须稍后释放它,但您可以毫无问题地访问它。
I marked the changes of the retains in your code, maybe it will become more clear.
when your retains drop to 0 the object doesn't exist anymore. Next time you try to access it your app crashs. Because of the autorelease this will happen after your autorelease pool gets drained, at an unknown point in the future after you have left the current method.
you have still retained that object. You have to release it later but you can access it without problems.
在第一种情况下,您不会使用合成的 setter,它负责保留对象。在这种情况下,当
theManager
自动释放时,_locationManager
不会保留任何内容,因此theManager
会被释放。第二种情况使用合成的setter(因为它通过
self
调用它),因此它在自动释放后保留theManager
。In the first instance, you aren't going through the synthesized setter, which takes care of retaining the object. In which case, when
theManager
is autoreleased_locationManager
is not holding on to anything, sotheManager
gets dealloced.The second case uses the synthesized setter (since it calls it through
self
) so it retainstheManager
after it is autoreleased.