保存时iphone核心数据未解决错误


169

尝试保存时,我从核心数据中收到一条奇怪的错误消息,但是该错误不可重现(在执行不同任务时,它出现在不同时间)

错误消息:

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
    }
}

知道这个消息的原因吗?使其随机出现


这可以帮助你:“iPhone核心数据‘生产’错误处理” stackoverflow.com/questions/2262704/...
约翰内斯Fahrenkrug

Answers:


296

这意味着有一个强制属性已分配为零。在* .xcodatamodel中,选中“可选”框,或者在保存到managedObjectContext时,确保您的属性已填写。

如果在更改代码以符合这两个要求后仍遇到进一步的错误,请尝试清理内部版本并从iPhone Simulator / iPhone设备中删除该应用程序。您的模型更改可能与旧模型实现冲突。

编辑:

我几乎忘了这是Core Data吐出的所有错误代码: Core Data常量参考 我以前对此很麻烦,并且意识到我没有选中正确的可选框。麻烦找出问题所在。祝好运。


2
这为我解决了。还要注意,至少以我的经验,即使没有将其保存到sqlite文件中,更改也确实进入了上下文。因此,发生这种情况时,行为可能会不稳定。
nickthedude

我无法找到根本原因,但是我设法通过使所有属性都可选来解决了这个问题。
2014年

您是否尝试过查尔斯的代码,它会告诉您哪个字段是问题所在。
David Wong

233

我自己为此挣扎了一段时间。真正的问题在于,您进行的调试未向您显示问题所在。原因是因为CoreData会将一个NSError对象数组放置在“顶级” NSError对象中,如果存在多个问题,它将返回该数组(这就是为什么您看到错误1560,该错误表示多个问题,以及一个错误数组1570年代)。似乎CoreData有一些键,用于存储错误中的信息,如果存在问题,该错误将为您提供更多有用的信息(例如发生错误的实体,丢失的关系/属性等) )。您可以在此处的参考文档中找到用于检查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]);
        }
    }

它将产生输出,告诉您缺少的字段,从而大大简化了解决问题的过程。


非常感谢此代码。这使得CoreData问题跟踪确实更加简单。
MiKL'7

21

我将其作为答案,即使它实际上更多地是对Charles片段的修饰。NSLog的直接输出可能会使阅读和解释变得一团糟,因此我喜欢在空白处插入一些关键的“ userInfo”键的值。

这是我一直在使用的方法的一个版本。(“ _sharedManagedObjectContext”是“ [[[[UIApplication sharedApplication]委托] managedObjectContext]”的#定义。)

- (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中遇到问题时,该值直接指向我在尝试保存之前忘记设置的非可选核心数据实体。


也很有用。特别是当您获得此原始\ n \ n \ n核心数据实体描述字符串时。
卢卡斯(Lukasz)

整齐。顺便说一下,“消息”未使用。
pojo 2014年

0

当我将第二条记录保存到CoreData时,这个问题触动了我。所有非可选字段(关系)也都填充为nil,但是在错误输出中,我注意到,第一个保存的对象中的一个字段变为nil。有点奇怪?但是原因很简单-当我在第二个对象中设置它时,一对一关系会使第一个对象无效。

因此,该方案是:

"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)

将“父级”中的关系从一对一更改为多对一即可解决此任务。



0

我的意思是您的模型无法验证,这可能由于多种原因而发生:模型中未使用的属性,缺少标记为必需的值。为了更好地了解到底出了什么问题,请在准备保存对象的地方放置一个断点,然后调用validateFor...方法变体之一,例如:

po [myObject validateForInsert]

有关该问题的更多详细信息,请参见错误描述。成功的验证意味着您将不会获得任何输出。


0

它帮助了我。也检查这个。

选中* .xcodatamodel对象中的选框

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.