CoreData 'Этот NSPersistentStoreCoordinator не имеет постоянных хранилищ. Он не может выполнить операцию сохранения.

Я следовал этим инструкциям, чтобы помочь интегрировать поддержку iCloud с CoreData, и я получаю некоторые ошибки.

У меня есть это в моем AppDelegate:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    //NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Little_Wedding_Book_Universal.sqlite"];
    NSString *storePath = [[NSString stringWithFormat:@"%@", [self applicationDocumentsDirectory]] stringByAppendingPathComponent:@"appname.sqlite"];
    NSURL *storeURL = [NSURL fileURLWithPath:storePath];

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    NSPersistentStoreCoordinator* psc = persistentStoreCoordinator;

    if (IOS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.0"))
    {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSFileManager *fileManager = [NSFileManager defaultManager];

            // Migrate datamodel
            NSDictionary *options = nil;

            // this needs to match the entitlements and provisioning profile
            NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:@"J9VXW4WCE8.com.company.appname"];
            NSString* coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:@"data"];
            if ([coreDataCloudContent length] != 0) {
                // iCloud is available
                cloudURL = [NSURL fileURLWithPath:coreDataCloudContent];

                options = [NSDictionary dictionaryWithObjectsAndKeys:
                           [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                           [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                           @"appname.store", NSPersistentStoreUbiquitousContentNameKey,
                           cloudURL, NSPersistentStoreUbiquitousContentURLKey,
                           nil];
            }
            else
            {
                // iCloud is not available
                options = [NSDictionary dictionaryWithObjectsAndKeys:
                           [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                           [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                           nil];
            }

            NSError *error = nil;
            [psc lock];
            if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
            {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
            [psc unlock];

            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"asynchronously added persistent store!");
                [[NSNotificationCenter defaultCenter] postNotificationName:@"RefetchAllDatabaseData" object:self userInfo:nil];
            });

        });

    }
    else
    {
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                                 nil];

        NSError *error = nil;
        if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
        {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }

    return persistentStoreCoordinator;
}

В другом контроллере представления я создаю экземпляр моего AppDelegate, создаю объект и вызываю [appDelegate saveContext]; Вот где происходит сбой приложения. Это всегда работало отлично (до сих пор добавлялась поддержка iCloud).

-(void)saveContext
{
    NSError *error;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            // Update to handle the error appropriately.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            exit(-1);  // Fail
        }
    }
}

Так что он падает при этом методе, и консоль выдает мне это сообщение:

'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores.  It cannot perform a save operation.'

Я не знаю, что делать, помогите!

РЕДАКТИРОВАТЬ: журнал консоли ниже:

При запуске приложения я получаю:

2012-08-22 17:39:47.906 appname[24351:707] asynchronously added persistent store!
2012-08-22 17:39:47.955 appname[24351:707] asynchronously added persistent store!

Последующие действия при сбое приложения:

2012-08-22 17:41:31.657 appname[24351:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This NSPersistentStoreCoordinator has no persistent stores.  It cannot perform a save operation.'
*** First throw call stack:
(0x3749d88f 0x351a2259 0x36bf0fe7 0x36c59287 0xd648b 0x149e0b 0x373f73fd 0x3118ce07 0x3118cdc3 0x3118cda1 0x3118cb11 0x3118d449 0x3118b92b 0x3118b319 0x31171695 0x31170f3b 0x33bb322b 0x37471523 0x374714c5 0x37470313 0x373f34a5 0x373f336d 0x33bb2439 0x3119fcd5 0xd53dd 0xd5378)
terminate called throwing an exception(lldb) 

person Josh Kahane    schedule 22.08.2012    source источник
comment
Фоновый поток (который получает постоянное хранилище iCloud) уже завершен до того, как вы сохраните контекст?   -  person Martin R    schedule 22.08.2012
comment
Как лучше это проверить?   -  person Josh Kahane    schedule 22.08.2012
comment
Ваш код выполняет NSLog(@"asynchronously added persistent store!");, когда фоновый поток завершается, так что вы должны это увидеть.   -  person Martin R    schedule 22.08.2012
comment
О да, это отображается почти мгновенно при запуске приложения, но когда дело доходит до сохранения, я никогда не вижу этого сообщения.   -  person Josh Kahane    schedule 22.08.2012
comment
Можете ли вы показать вывод NSLog вашей программы?   -  person Martin R    schedule 22.08.2012
comment
Я обновил свой вопрос с содержимым журнала. Загадочная вещь, по крайней мере для меня.   -  person Josh Kahane    schedule 22.08.2012
comment
давайте продолжим обсуждение в чате   -  person Martin R    schedule 22.08.2012
comment
У меня такая же ошибка, как решить?   -  person Alexander Sharunov    schedule 15.11.2012


Ответы (9)


Вероятно, вы вызываете метод persistentStoreCoordinator из двух (или более) разных потоков. Либо прямо, либо косвенно.

Как написано, этот метод не является потокобезопасным.

Возможно, у вас есть другие методы с той же проблемой. Обычно managedObjectContext существует и записывается аналогичным образом.

Есть два способа решить эту проблему:

  • используйте @synchronize, чтобы сделать эти методы потокобезопасными
  • переместите код инициализации из них в метод инициализации и измените их, чтобы утверждать/кроме случаев, когда ivar равен nil

Второе, что вы также можете сделать неправильно, — это изменить контекст (например, добавить в него новые управляемые объекты), а затем попытаться сохранить его до того, как хранилище будет инициализировано.

Чтобы решить эту проблему, обязательно выполните одно из следующих действий:

  • вы не добавляете какой-либо управляемый объект в контекст, если вы не знаете, что в нем уже есть хотя бы один управляемый объект (подразумевается, что хранилище загружено)
  • если вам нужно добавить управляемый объект в контекст, не проверяя, что он уже есть (например, после первоначального создания пустого хранилища), убедитесь, что хранилище уже инициализировано (например, сделайте это, когда вы получите уведомление RefetchAllDatabaseData и вы обратите внимание, что база данных пуста).
person Analog File    schedule 22.08.2012
comment
Я столкнулся с той же проблемой, что и Джош Кахане, но, пожалуйста, скажите мне, как я могу использовать синхронизацию в persistenceStoreCoordinator? Пожалуйста, ответь мне - person Nikunj Jadav; 31.10.2013
comment
Для меня: второй более вероятен: потому что PSContainer.loadPersistentStores { ... завершается только тогда, когда вызывает это закрытие! поэтому немедленный возврат может привести к тому, что вы используете хранилище, которое еще не загружено (только на долю секунды) - person brahimm; 16.11.2019

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

person edzio27    schedule 25.02.2013
comment
Можно подумать, я уже не забуду это сделать. Спасибо, что быстро напомнили! - person Jacob Kranz; 26.02.2014
comment
Это работает только в том случае, если вы не загрузили свое приложение в магазин приложений. В противном случае это приведет к сбою приложения для всех пользователей, которые загрузили предыдущую версию и обновили ее новой версией. - person Eugene Pavlov; 12.07.2017

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

person surga    schedule 15.09.2016

Решено перемещением let moc = DataController().managedObjectContext в верхнюю часть класса, а не оставлением внутри функции seedPerson().

person Arkelyan    schedule 20.06.2016

Я видел эту ошибку во время тестирования, когда я раскрутил несколько временных NSManagedObjectContext, не цепляясь за них где-либо - ARC случайно освобождал контекст из-под меня.

В результате получилось сохранить ссылку на MOC в тестах и ​​сбросить ее для каждого теста.

Не уверен, насколько это актуально для обстоятельств, не связанных с тестированием, но, особенно если вы используете дочерние/родственные контексты, стоит убедиться, что они действительно все еще существуют. :П

person DesignatedNerd    schedule 28.02.2017

У меня такая же проблема. Причина, по которой я получаю сообщение об ошибке, заключалась в том, что я внес незначительные изменения в свою схему объекта CoreData (в основном я добавил 2-3 новых атрибута). И я забыл об этом, так как он не выдает никаких ошибок, пока мы его не запустим. Итак, что происходит, приложение, которое работало ранее, уже имело постоянное хранилище с предыдущей схемой. Итак, новая схема указывает на тот же магазин. Вот почему мы получаем ошибку, когда запускаем его, когда пытаемся получить доступ к новым атрибутам.

Решение. Удалите приложение с устройства/симулятора. И переустановите его. (Новая сборка будет иметь новую схему и, следовательно, не будет аварийно завершать работу.)

person Priyanka    schedule 08.09.2017

Обновление ре. XCODE 4.6.3 и MACOSX 10.9.5:

Чтобы решить эту проблему, я удалил каталог приложения, связанный с продуктом, в расположении производных данных xcode:

rm -rd /Пользователи//Библиотека/Разработчик/Xcode/ПроизводныеДанные/. Очевидно, данные перепутались после игры с объектной моделью.

person mdohmen    schedule 22.09.2014

Я тоже застрял с этой проблемой. Для этого я сначала проверил основной код переноса данных. Поскольку в моем случае код был правильным, я удалил свое приложение с устройства и переустановил его. И это работает.

person bittu    schedule 01.06.2017

Для меня я обнаружил, что addPersistentStoreWithType всегда возвращает nil в моем случае. Таким образом, постоянное хранилище не было успешно создано. Затем я печатаю storeURL

~/Library/Developer/CoreSimulator/Devices/1F8C6299-1F80-4212-9FE2-CA33BD365851/data/Containers/Data/Application/9CA7B7BB-A835-4BC2-B12D-23B84D420F91/Library/Documentation/my-database.sqlite

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

  • Я должен использовать NSDocumentDirectory вместо NSDocumentationDirectory. Автодополнение кода в Xcode предлагает каталог документации перед перечислением каталога документов.

  • Когда я использовал NSDocumentationDirectory, NSPersistentStoreCoordinator всегда пытался создать постоянное хранилище в .../Library/Documentation/my-database.sqlite, что является недопустимым путем.

  • Вместо этого правильный путь должен быть .../Documents/BeeLocation.sqlite.
person RY_ Zheng    schedule 08.06.2020