为啥我需要保留NSDateFormatter dateFromString的结果:

Posted

技术标签:

【中文标题】为啥我需要保留NSDateFormatter dateFromString的结果:【英文标题】:Why do I need to retain the result of NSDateFormatter dateFromString:为什么我需要保留NSDateFormatter dateFromString的结果: 【发布时间】:2011-11-11 00:04:43 【问题描述】:

我有一个 NSDate*,我将其存储为带有 retain 关键字的属性:

@property (nonatomic, retain) NSDate* startTime;

我是这样使用的:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"h:mm a"];
startTime = (NSDate*)[[NSUserDefaults] standardUserDefaults] objectForKey:@"StartTimeKey"];
if (startTime == nil)
  startTime = [[dateFormatter dateFromString:@"8:00 am"] retain];

为什么我需要保留dateFromString:消息的结果,而我不需要保留objectForKey:的结果?

我刚刚升级到 XCode 4.2,现在我正在使用 LLVM GCC 4.2 编译器。在升级之前,代码在没有保留的情况下运行良好。现在它在没有保留消息的情况下崩溃(稍后在我访问 startDate 属性时的代码中)。

【问题讨论】:

按照规则,你不应该保留它,因为 dateFromString 会自动释放,但 startTime 属性应该保留分配,因为它被归因于保留 顺便说一句,看起来像 dataFormatter 泄漏(如果你不使用 ARC)。 @DavidDunham - 我认为这是standardUserDefaults objectForKey:泄漏。 【参考方案1】:

问题是你写了这个:

startTime = blah blah blah;

您正在直接设置实例变量startTime。如果您改为这样做:

self.startTime = blah blah blah;

然后编译器会把它变成这样:

[self setStartTime:blah blah blah];

自动生成的setter方法会为你做retain。

如果你这样做:

@synthesize startTime = _startTime;

那么实例变量将被命名为_startTime,这样更容易记住使用属性而不是直接分配给实例变量。

【讨论】:

+1 - 顺便说一下,这就是为什么我喜欢用 iVar 的 _startTime 之类的东西来区分 iVar 和属性。那么直接去iVar的时候就很清楚了。 @rob - 感谢您的澄清。我一直在错误地假设startTimeself.startTime 的同义词和快捷方式现在我看到它们确实引用了同一个对象,但是当使用self.startTime 访问该属性时,XCode 将添加神奇的隐藏代码来做保留。 尚不清楚为什么 standardUserDefaults objectForKey: 似乎在上面的代码中添加了额外的保留计数。 standardUserDefaults 没有添加保留供您使用。它可能会将值保存在自己的私有字典中,因此它保留该值的时间比您使用它的时间长。另一方面,dateFormatter 正在创建一个新的 NSDate 并自动释放它,所以如果你不保留它,它会在下一次运行循环中消失。【参考方案2】:

答案在第 11 页的内存管理编程指南中。

你拥有一个你创建的对象(也就是说你不需要保留它,它已经完成了)。您可以使用 alloc、new、copy 或 mutablecopy 创建一个对象。

在这种情况下,dateFormatter 会为您提供一个新对象,但由于您没有自己调用 alloc、new 或复制,dateFormatter 将调用(通常是它的工作方式)新 NSDAte 对象上的 autorealease。

但是,如果您使用 setter 和 getter 设置属性,则不会有这个问题。

【讨论】:

感谢您的回答。正如我在对@rob 的回答的评论中提到的那样,我以为我在设置属性,并没有意识到我实际上是在给 iVar 赋值,因此绕过了 setter。

以上是关于为啥我需要保留NSDateFormatter dateFromString的结果:的主要内容,如果未能解决你的问题,请参考以下文章

为啥在启用 ARC 的项目中不需要维护保留计数

NSDateFormatter 和 NSDateComponents 为周数返回不同的值

为啥需要保留 NSString 变量?

NSDateFormatter dateFromString 格式字符串问题

Swift获取当前时间(年月日),按网上说的,可是为啥找不到NSCalendarDate

使用 NSDateFormatter 格式化月份和年份返回无效日期