NSDate保留发送到解除分配实例的消息

时间:2011-03-24 23:21:29

标签: iphone cocoa ios nsdate nsuserdefaults

我在使用NSDate时遇到了一些问题并将其保存在NSUserDefaults中。它接着每隔一次NSUserDefaults保存我的NSDate,它不能因为它被解除分配并在日志中显示此错误。

-[__NSDate retain]: message sent to deallocated instance 0x4c20c80

我知道NSDate以与普通对象不同的方式分配和释放,但我想知道是否有人知道是否通过使用:

- (void)saveData
{
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
[data setObject:dateOpened forKey:@"dateOpened"];
[dData synchronize];
}

...或...

- (void)loadData
{
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
dateOpened = [data objectForKey:@"dateOpened"];
}

我正在发布我的NSDate实例,所以给它一个保留计数为0所以我的应用程序在尝试时无法再次保存它?

我正在使用:

@property (retain) NSDate *dateOpened;

任何想法都会非常感激,因为我想解决这个问题。我只学了大约4个月左右的时间,我的第一个应用程序差不多完成了,这是一个主要的扳手!

非常感谢,如果您需要更多关于我正在做的事情的代码或信息,请告诉我。 :-D

3 个答案:

答案 0 :(得分:2)

就内存管理而言,NSDate与任何其他对象的行为没有任何不同。你可能指的是,通常使用像[NSDate date]这样的便利操作符返回一个自动释放的对象(意味着该对象将在主循环结束时删除(或者每当释放自动释放池时),除非另一个类调用保留在它上面。因为我看不到你的所有代码我只能做出有根据的猜测,但我相信你正在调用从[data objectForKey:]返回的对象的释放,这将是你的错误。该函数返回一个自动释放的对象,因此你没有对象的“所有权”,直到你在它上面调用retain。如果你没有调用retain,或者显式地分配它,你就不应该在它上面调用release(这适用于所有对象) )。

答案 1 :(得分:0)

您遇到的问题在于您的-loadData方法。

dateOpened = [data objectForKey:@"dateOpened"];

如果是上面一行,你是直接访问ivar而不是通过保留的属性。所以你有两种选择之一。

// First choice retain it yourself
dateOpened = [data objectForKey:@"dateOpened"];
[dateOpened retain];

或者

// Second choice have the @property do it for you
[self setDateOpened:[data objectForKey:@"dateOpened"]];

这就是为什么在您的私人ivars上使用下划线是个好主意,因此您知道何时直接访问它们。你将犯很少的错误。 :)

// declaring it with underscore would have caught your mistake.
NSDate *_dateOpened;

答案 2 :(得分:0)

loadData中的问题是您直接将dateOpened分配给自动释放的值,一旦事件循环通过,该值将无效。

- (void)loadData
{
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];

// dateOpened = [data objectForKey:@"dateOpened"];

// try:
   self.dateOpened = [data objectForKey:@"dateOpened"];

// which is basically the same as:
// [self setDateOpened:[data objectForKey:@"dateOpened"]];

// the following 2 lines could also work:
// [dateOpened release];
// dateOpened = [[data objectForKey:@"dateOpened"] retain];

}

如果您有@synthesized dateOpened,那么您可以想象已经为您的班级添加了以下两种方法:

- (NSDate *)dateOpened {
  return dateOpened;
}

- (void)setDateOpened:(NSDate *)aDate {
  [aDate retain];
  [dateOpened release];
  dateOpened = aDate;
}