我在尝试保存时从核心数据中收到一条奇怪的错误消息 但是错误不可重现的问题(在执行不同任务时出现在不同时间)
错误消息:
Unresolved error Domain=NSCocoaErrorDomain Code=1560 UserInfo=0x14f5480 "Operation could not be completed. (Cocoa error 1560.)", {
NSDetailedErrors = (
Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x5406d70 "Operation could not be completed. (Cocoa error 1570.)",
Error Domain=NSCocoaErrorDomain Code=1570 UserInfo=0x14f9be0 "Operation could not be completed. (Cocoa error 1570.)"
);
}
,生成错误的方法是:
- (IBAction)saveAction:(id)sender {
NSError *error;
if (![[self managedObjectContext] save:&error]) {
// Handle error
NSLog(@"Unresolved error %@, %@, %@", error, [error userInfo],[error localizedDescription]);
exit(-1); // Fail
}
}
任何关于此消息的原因的想法?让它随机出现
答案 0 :(得分:292)
这意味着强制属性已被指定为零。在* .xcodatamodel中检查“可选”框或保存到managedObjectContext时确保填写了属性。
如果在更改代码后出现进一步的错误以满足这两个要求,请尝试清理构建并从iPhone模拟器/ iPhone设备中删除该应用程序。您的模型更改可能与旧模型实现发生冲突。
编辑:
我差点忘了这里核心数据吐出的所有错误代码: Core Data Constants Reference 之前我遇到了麻烦,我意识到我取消选中了正确的可选框。找出问题的麻烦。祝你好运。
答案 1 :(得分:232)
我自己挣扎了一会儿。这里真正的问题是你得到的调试并没有告诉你问题是什么。原因是因为如果存在多个问题,CoreData会将NSError对象的数组放入它返回的“顶级”NSError对象中(这就是为什么你看到错误1560,这表明存在多个问题,以及一个错误数组) 16世纪70年代)。看起来CoreData有一些密钥用于存储它返回的错误中的信息,如果存在可以提供更多有用信息的问题(例如发生错误的实体,缺少的关系/属性等等) )。您可以在the reference docs here。
中找到用于检查userInfo字典的密钥这是我用来从保存期间返回的错误中获得合理输出的代码块:
NSError* error;
if(![[survey managedObjectContext] save:&error]) {
NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0) {
for(NSError* detailedError in detailedErrors) {
NSLog(@" DetailedError: %@", [detailedError userInfo]);
}
}
else {
NSLog(@" %@", [error userInfo]);
}
}
它将生成输出,告诉您缺少的字段,这使得解决问题变得更加容易处理。
答案 2 :(得分:21)
我把它作为一个答案,尽管这更像是对Charles的片段的修饰。 NSLog的直接输出可能是一个混乱的读取和解释,所以我喜欢抛出一些空格并调出一些关键的'userInfo'键的值。
这是我一直使用的方法的一个版本。 ('_sharedManagedObjectContext'是'[[[UIApplication sharedApplication]委托] managedObjectContext的'#fine]'。)
- (BOOL)saveData {
NSError *error;
if (![_sharedManagedObjectContext save:&error]) {
// If Cocoa generated the error...
if ([[error domain] isEqualToString:@"NSCocoaErrorDomain"]) {
// ...check whether there's an NSDetailedErrors array
NSDictionary *userInfo = [error userInfo];
if ([userInfo valueForKey:@"NSDetailedErrors"] != nil) {
// ...and loop through the array, if so.
NSArray *errors = [userInfo valueForKey:@"NSDetailedErrors"];
for (NSError *anError in errors) {
NSDictionary *subUserInfo = [anError userInfo];
subUserInfo = [anError userInfo];
// Granted, this indents the NSValidation keys rather a lot
// ...but it's a small loss to keep the code more readable.
NSLog(@"Core Data Save Error\n\n \
NSValidationErrorKey\n%@\n\n \
NSValidationErrorPredicate\n%@\n\n \
NSValidationErrorObject\n%@\n\n \
NSLocalizedDescription\n%@",
[subUserInfo valueForKey:@"NSValidationErrorKey"],
[subUserInfo valueForKey:@"NSValidationErrorPredicate"],
[subUserInfo valueForKey:@"NSValidationErrorObject"],
[subUserInfo valueForKey:@"NSLocalizedDescription"]);
}
}
// If there was no NSDetailedErrors array, print values directly
// from the top-level userInfo object. (Hint: all of these keys
// will have null values when you've got multiple errors sitting
// behind the NSDetailedErrors key.
else {
NSLog(@"Core Data Save Error\n\n \
NSValidationErrorKey\n%@\n\n \
NSValidationErrorPredicate\n%@\n\n \
NSValidationErrorObject\n%@\n\n \
NSLocalizedDescription\n%@",
[userInfo valueForKey:@"NSValidationErrorKey"],
[userInfo valueForKey:@"NSValidationErrorPredicate"],
[userInfo valueForKey:@"NSValidationErrorObject"],
[userInfo valueForKey:@"NSLocalizedDescription"]);
}
}
// Handle mine--or 3rd party-generated--errors
else {
NSLog(@"Custom Error: %@", [error localizedDescription]);
}
return NO;
}
return YES;
}
这允许我看到'NSValidationErrorKey'的值,当我从OP遇到问题时,它直接指向我在尝试保存之前忘记设置的非可选Core Data实体。
答案 3 :(得分:0)
当我将第二条记录保存到CoreData时,问题触动了我。 所有非可选字段(关系)也没有填充,但在错误输出中我注意到,第一个保存对象中的一个字段已变为零。奇怪一点?但原因很简单 - 当我在第二个对象中设置它时,一对一关系会使第一个对象无效。
所以,该计划是:
"Parent" with relationship "child" One to One
Create Child 1, set parent. Save - OK
Create Child 2, set parent. Save - Error, Child 1.Parent == nil
(behind the scene child 2 did nullify child 1 parent)
将父对象中的关系从一对一更改为多对一解决了此任务。
答案 4 :(得分:0)
我有int类型的瞬态属性,不是可选的。显然,当它设置为0时,会出现1570错误。刚刚将我的所有瞬态属性更改为可选。如有必要,可以在代码中实现零检查逻辑。
答案 5 :(得分:0)
我的意思是您的模型无法验证,这可能由于多种原因而发生:模型中未使用的属性,缺少标记为必需的值。
为了更好地理解究竟出现了什么问题,请在准备好保存对象的地方放置一个断点,然后调用validateFor...
方法变体之一,例如:
po [myObject validateForInsert]
有关此问题的更多详细信息,请参阅错误说明。成功验证意味着您将无法获得输出。
答案 6 :(得分:0)
它帮助了我。也检查一下。
选中* .xcodatamodel对象中的可选框