我在使用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
答案 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;
}