iPhone Core Data неразрешенная ошибка при сохранении



Я получаю странное сообщение об ошибке из основных данных при попытке сохранения
но проблема в том, что ошибка не воспроизводима ( она появляется в разное время при выполнении разных задач)



сообщение об ошибке:



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


есть идеи по причине этого сообщения ? учитывая, что он появляется в случайные моменты времени

582   6  

6 ответов:

Это означает, что обязательное свойство было присвоено nil. Либо в вашем *.xcodatamodel установите флажок "необязательно" или при сохранении в managedObjectContext убедитесь, что ваши свойства заполнены.

Если вы получаете дополнительные ошибки после изменения кода в соответствии с двумя требованиями, попробуйте очистить свою сборку и удалить приложение с вашего устройства iPhone Simulator/iPhone. Изменение модели может конфликтовать со старой моделью реализация.

Edit:

Я почти забыл вот все коды ошибок, которые выплевывает Core Data: Ссылка На Константы Основных Данных У меня были проблемы с этим раньше, и я понял, что я не правильный дополнительный ящик. Такие проблемы с выяснением проблемы. Удача.

Я сам некоторое время боролся с этим. Реальная проблема здесь заключается в том, что отладка у вас не отображается, в чем проблема. Причина этого заключается в том, что CoreData помещает массив объектов NSError в объект NSError "верхнего уровня", который он возвращает, если существует более одной проблемы (именно поэтому вы видите ошибку 1560, которая указывает на несколько проблем и массив ошибок 1570s). Похоже, что 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]);
        }
    }

он будет производить вывод, который сообщает вам поля, которые отсутствуют, которые это значительно облегчает решение проблемы.

Я бросаю это в качестве ответа, хотя на самом деле это скорее украшение фрагмента Чарльза. Прямой вывод из NSLog может быть беспорядком для чтения и интерпретации, поэтому мне нравится бросать некоторые пробелы и вызывать значение некоторых критических ключей "userInfo".

вот версия метода, который я использовал. ('_sharedManagedObjectContext' - это #define для ' [[[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, указывало непосредственно на необязательные сущности Core Data, которые я забыл установить перед попыткой сохранить.

проблема коснулась меня, когда я сохраняю вторую запись в 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)

изменение отношения в Родительском от одного к одному ко многим Один решил эту задачу.

У меня было переходное свойство типа int, которое не было необязательным. Очевидно, что когда он был установлен в 0, появляется ошибка 1570. Просто изменил все мои переходные свойства на необязательные. При необходимости логика нулевой проверки может быть реализована в коде.

I означает, что ваша модель не прошла проверку, что может произойти по ряду причин: неиспользуемое свойство в вашей модели, отсутствующее значение, отмеченное как необходимое. Чтобы лучше понять, что именно пошло не так, поместите точку останова в место, где вы готовы сохранить свой объект, и вызовите один из validateFor... варианты метода, например:

po [myObject validateForInsert]

более подробная информация о проблеме находится в описании ошибки. Успешная проверка означает, что вы будете не получить никакого выхода.

Comments

    Ничего не найдено.