将NSDate保存到CoreData上下文时出现问题

时间:2011-02-27 16:59:35

标签: iphone objective-c ios core-data

我正在尝试使用属性类型Date之一将托管对象保存到managedObjectContext

代码就像:

reminder.eventDate = selectedDate;
NSLog(@"Date: %@", selectedDate);
NSError *error = nil;
if (![reminder.managedObjectContext save:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}
上下文保存程序中的

与SIGABRT崩溃。这是一个控制台日志:

2011-02-28 00:50:18.817 MyApp[9021:207] *** Terminating app due to uncaught 
exception 'NSInvalidArgumentException', reason: '-[__NSDate isEqualToString:]: 
unrecognized selector sent to instance 0x4e73490'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x01057be9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x011ac5c2 objc_exception_throw + 47
    2   CoreFoundation                      0x010596fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x00fc9366 ___forwarding___ + 966
    4   CoreFoundation                      0x00fc8f22 _CF_forwarding_prep_0 + 50

有谁知道我为什么这么做? 第二个问题是为什么当我检入调试器模式时selectedDate不是NSDate类型而是__NSDate(前面是双下划线)。

谢谢!

更新

我做了一些更改,以便更容易地捕获bug。现在代码就像:

reminder.eventDate = [NSDate date];
NSLog(@"Date: %@", selectedDate);
NSError *error = nil;
if (![reminder.managedObjectContext save:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

所以,这里我们肯定保存NSDate。 reminder.eventDate也是NSDate。但我仍然有这个错误。如果我评论reminder.eventDate = [NSDate date];保存抛出另一个错误(日期是NSData中的必填字段,那么保存:返回错误“操作无法完成。”与eventDate = nil;。 CoreData结构被多次检查 - eventDate具有Date类型。

UPDATE(问题解决):最后我发现了问题。 eventDate被设置为我的tableview单元格中detailTextLabel.text的键(我使用了KVO)。因此,如果没有直接调用,我无法找到eventDate的任何方法调用。奇怪的是,崩溃发生在save方法上,而不是以后。在调用堆栈中根本没有tableView:cellForRowAtIndexPath:方法......

5 个答案:

答案 0 :(得分:7)

听起来很傻,我建议您仔细检查提醒对象和关联的managedObjectContext是否都有效。

您确定模型正确地将eventDate建模为日期属性,并且您还确定传递给eventDate属性的对象是NSDate对象。因此,请尝试验证提醒及其managedObjectContext不是nil。

最后,验证是否正确设置了所有其他属性和关系(检查是否实际插入了所有必需的属性和关系,检查您使用的对象是否具有正确的类型等)。

这也有助于缩小可能性。

编辑:您可以验证sqlite数据库中实际发生的情况。在开始申请之前,只需添加以下内容作为参数:

-com.apple.CoreData.SQLDebug 1

请参阅documentation

如何执行此操作取决于您安装的工具集(Xcode 3或4)。我正在使用最新的Xcode 4并添加一个参数,您只需选择当前的方案,然后选择运行“您的应用程序名称”并单击Arguments选项卡以添加参数。

答案 1 :(得分:6)

听起来您的数据模型设置为期望eventDate属性中的字符串,而不是日期。

答案 2 :(得分:3)

NSDate是一个“类集群”,这意味着您实际处理的实例将是NSDate的某个私有子类的实例(在本例中为__NSDate)。

至于错误,我同意Simon Goldeen的观点,最可能的原因是数据模型或NSManagedObject子类需要字符串而不是日期。

答案 3 :(得分:2)

只是添加到已经说过的内容:

它不一定是模型或NSManagedObject子类的问题。它几乎可以是调用isEqualToString:的任何地方的一段代码。在某个地方,你有一个代码假定的对象应该是一个NSString,而是一个NSDate对象。我会查看任何可能将日期转换为字符串的代码。

但是,由于它在保存时发生,我会查看您可能对子类进行的任何自定义。

开始的地方是搜索项目isEqualToString:

<强>更新

由于isEqualToString是一种测试方法,因此只要您对字符串进行比较(例如排序),就可以激活它。我无法重现您的确切错误,但以下代码执行类似的操作:

id idDate=[NSDate date];
NSString *bob=[NSString stringWithString:@"bob"];
NSString *steve=@"test this";
steve=idDate;
NSLog(@"test=%@",([steve compare:bob]) ?@"YES":@"NO");

...遵守但抛出异常:

-[NSCFString timeIntervalSinceReferenceDate]: unrecognized selector sent to instance 0x4040

所以,你可以看到这些类型的错误是如何进入的。这也是为什么你应该谨慎使用id的一个例子。

答案 4 :(得分:0)

我也追了这个。由于您的模型和类定义很好,并且假设您的价值很好,那么有一个不太明显的地方为我修复它...从设备中删除应用程序并清理您的构建,并确保任何种子sqlite文件是新的太。我的设备或构建文件夹有一个旧的商店或模型挥之不去导致这种情况。您使用了哪些其他框架? RestKit,JSON等?任何重载类方法的东西也可能是一个嫌疑人。 ...很难说是什么比较保存...我的猜测是一个旧商店