Неверная ошибка iphone Core при сохранении
Я получаю странное сообщение об ошибке из основных данных при попытке сэкономить
но проблема в том, что ошибка не воспроизводится (она появляется в разное время при выполнении разных задач)
сообщение об ошибке:
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
}
}
любая идея по причине этого сообщения? что он появляется в случайное время
Ответы
Ответ 1
Это означает, что обязательное свойство было присвоено nil. Либо в *.xcodatamodel проверьте флажок "Необязательный", либо когда вы сохраняете файл managedObjectContext, убедитесь, что ваши свойства заполнены.
Если вы получаете дополнительные ошибки после изменения кода в соответствии с двумя требованиями, попробуйте очистить свою сборку и удалить приложение с вашего iPhone Simulator/iPhone. Изменение модели может противоречить реализации старой модели.
Edit:
Я почти забыл здесь все коды ошибок, которые вырывает Core Data:
Ссылка на константу основных данных
У меня были проблемы с этим раньше, и я понял, что не снял правильную дополнительную коробку. Такая проблема выясняет проблему. Удачи.
Ответ 2
Я немного с этим боролся. Реальная проблема здесь в том, что отладка, которую у вас есть, не показывает вам, в чем проблема. Причина этого заключается в том, что 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]);
}
}
Он будет выводить выходные данные, которые сообщают вам о потерянных областях, что значительно затрудняет устранение проблемы.
Ответ 3
Я бросаю это в качестве ответа, хотя это действительно больше приукрашивает фрагмент Чарльза. Прямой вывод из NSLog может быть бесполезным для чтения и интерпретации, поэтому мне нравится бросать какое-то пустое пространство и вызывать значение некоторых критических "пользовательских" ключей.
Здесь версия метода, который я использовал. ('_sharedManagedObjectContext' является #define для '[[[UIApplication sharedApplication] delegate] managedObjectContext]'.)
- (BOOL)saveData {
NSError *error;
if (![_sharedManagedObjectContext save:&error]) {
// If Cocoa generated the error...
if ([[error domain] isEqualToString:@"NSCocoaErrorDomain"]) {
// ...check whether there 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 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, которые я забыл установить, прежде чем пытаться сохранить.
Ответ 4
Проблема коснулась меня, когда я сохранил вторую запись в 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)
Изменение отношения в родительском от одного до одного к многим к одному разрешило эту задачу.
Ответ 5
У меня было свойство transient типа int, которое не было необязательным. Очевидно, когда было установлено 0, появится ошибка 1570. Просто изменил все мои свойства переходного процесса на факультативный. Логика Nil-check может быть реализована в коде при необходимости.
Ответ 6
Я имею в виду, что ваша модель не прошла проверку, что может произойти по ряду причин: неиспользуемое свойство в вашей модели, отсутствующее значение, которое помечается как требуется.
Чтобы лучше понять, что именно пошло не так, поставьте точку останова в том месте, где вы готовы сохранить свой объект, и вызовите один из вариантов метода validateFor...
, например:
po [myObject validateForInsert]
Более подробная информация о проблеме приведена в описании ошибки. Успешная проверка означает, что вы не получите выход.