Iphone - 分配属性和实例变量

发布于 2024-11-12 16:50:25 字数 758 浏览 5 评论 0原文

好吧,我仍然对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

此刻的回忆 2024-11-19 16:50:25

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

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

是由使用 autorelease 引起的。 autorelease可以理解为:在不久的将来的某个时刻,release自动释放这个对象。考虑到通过释放池实现自动释放的方式,这通常会在下次控制流返回主循环并且释放池被清空时发生。

因此,在第一种情况下,您正在创建对象并将其存储在 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 就像延迟释放一样,因此同时(在释放实际完成之前,这意味着在方法的其余部分和主循环之前的调用者中)您可以使用对象安全,然后它将被释放。

The problem you have in your first example:

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

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 way autorelease 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:

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

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:

  1. alloc will set the retain count to 1;

  2. retain properties will increment the retain count when assigning to them;

  3. 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.

最佳男配角 2024-11-19 16:50:25

我在你的代码中标记了retains的变化,也许它会变得更清楚。

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

当你的retains下降到0时,该对象就不再存在了。下次您尝试访问它时,您的应用程序会崩溃。由于自动释放,这种情况会在您的自动释放池耗尽后发生,在您离开当前方法后的未知时刻。


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

你仍然保留了那个对象。您必须稍后释放它,但您可以毫无问题地访问它。

I marked the changes of the retains in your code, maybe it will become more clear.

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

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.


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

you have still retained that object. You have to release it later but you can access it without problems.

行雁书 2024-11-19 16:50:25

在第一种情况下,您不会使用合成的 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, so theManager gets dealloced.

The second case uses the synthesized setter (since it calls it through self) so it retains theManager after it is autoreleased.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文