Основні дані 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 / ...
Johannes Fahrenkrug

Відповіді:


296

Це означає, що обов'язковій власності призначено нуль. Або у вашому * .xcodatamodel встановіть прапорець "необов'язково", або коли ви зберігаєте в ManagedObjectContext, переконайтеся, що ваші властивості заповнені.

Якщо ви отримуєте додаткові помилки після зміни коду, щоб відповідати двом вимогам, спробуйте очистити збірку та видаліть програму зі свого пристрою iPhone Simulator / iPhone. Ваша зміна моделі може суперечити застосуванню старої моделі.

Редагувати:

Я майже забув ось усі коди помилок, які випльовує Core Data: Посилання на базові константи даних У мене були проблеми з цим раніше, і я зрозумів, що я не встановив правильність додаткового поля. Така неприємність у з'ясуванні проблеми. Удачі.


2
Це вирішило це для мене. Також зауважте, що, принаймні з мого досвіду, навіть якщо він не був збережений у файлі sqlite, зміни все-таки пробилися в контекст. Тож поведінка може бути помилковою, коли це станеться.
nickthedude

Я не зміг отримати першопричину, але мені вдалося усунути проблему, зробивши всі властивості необов’язковими.
Михайло Ософський

Якщо ви спробували код Чарльза, він би сказав вам, у якому полі є проблема.
Девід Вонг

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

21

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

Ось версія методу, яким я користувався. ('_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'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", яке, коли я стикався з проблемою в ОП, вказувало безпосередньо на необов'язкові об'єкти основних даних, які я забув встановити, перш ніж намагатися зберегти.


Також дуже корисно. Особливо, коли ви отримуєте ці необроблені \ n \ n \ n основні рядки опису об'єкта даних.
Лукаш

Акуратний. 'повідомлення' не використовується BTW.
pojo

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)

Зміна відносин у Батьку з одного на один на багато в одного вирішила цю задачу.


0

У мене було тимчасове властивість типу int, яке було необов’язковим. Очевидно, що коли було встановлено значення 0, з’являється помилка 1570. Просто змінив усі мої перехідні властивості на необов'язкові. Логіка Nil-check при необхідності може бути реалізована в код.


0

Я маю на увазі, що вашу модель не вдалося перевірити, що може статися з кількох причин: невикористане властивість у вашій моделі, відсутність значення, яке позначено як необхідне. Щоб краще зрозуміти, що саме пішло не так, поставте крапку в місці, де ви готові зберегти ваш об'єкт, і зателефонуйте до одного з validateFor...варіантів методу, наприклад:

po [myObject validateForInsert]

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


0

Це мені допомогло. Перевірте і цей.

Перевірте додатковий ящик в вашому * об'єктах .xcodatamodel

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.