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, за да направите тези методи нишково безопасни
  • преместете кода за инициализиране от тях и в init метод и ги модифицирайте така, че да assert/освен ако ivar е nil

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

За да разрешите това, уверете се, че правите едно от следните:

  • не добавяте никакъв управляван обект към контекста, освен ако не знаете, че вече има поне един управляван обект в него (което означава, че магазинът е зареден)
  • ако трябва да добавите управляван обект към контекста, без да проверите дали вече има такъв (например след като първоначално създадете празния магазин), уверете се, че магазинът вече е инициализиран (например направете го, когато получите известието RefetchAllDatabaseData и вие забележете, че базата данни е празна).
person Analog File    schedule 22.08.2012
comment
Изправен съм пред същия проблем като Josh Kahane, но моля, кажете ми как мога да използвам синхронизиране в persistentStoreCoordinator? Моля, отговорете ми - 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

Видях тази грешка по време на тестване, когато завъртях някои временни NSManagedObjectContexts, без да ги закача никъде - контекстът щеше да бъде освободен изпод мен на случаен принцип от ARC.

Това, което приключи работа, беше да се запази препратка към MOC на тестовете и да се нулира за всеки тест.

Не съм сигурен доколко това е уместно за нетестови обстоятелства, но особено ако използвате контексти дете/брат, струва си да се уверите, че те действително все още са там. :P

person DesignatedNerd    schedule 28.02.2017

Имах същия проблем. Причината, поради която получавах грешката, беше, че бях направил някои дребни промени в моята схема на CoreData Entity(По принцип добавих 2-3 нови атрибута). И забравих за него, тъй като не дава никакви грешки, докато не го стартираме. Така че това, което се случва, е, че приложението, което се изпълняваше по-рано, вече имаше постоянното хранилище с предишната схема. Така че новата схема сочи към същия магазин. Ето защо получаваме грешката, когато го стартираме, докато се опитваме да получим достъп до новите атрибути.

Решение: Изтрийте приложението от устройството/симулатора. И го преинсталирате. (Новата компилация ще има новата схема и следователно няма да се срине.)

person Priyanka    schedule 08.09.2017

Актуализация re. XCODE 4.6.3 и MACOSX 10.9.5:

За да реша проблема, премахнах директорията на приложението, свързана с продукта в местоположението на извлечените от xcode данни:

rm -rd /Потребители//Библиотека/Разработчик/Xcode/DerivedData/. Очевидно данните се объркват след игра с обектния модел.

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 предлага директорията с документация преди enum на директорията на документа.

  • Когато използвах NSDocumentationDirectory, NSPersistentStoreCoordinator винаги се опитваше да създаде постоянното хранилище в .../Library/Documentation/my-database.sqlite, което е невалиден път.

  • Вместо това правилният път трябва да бъде .../Documents/BeeLocation.sqlite.
person RY_ Zheng    schedule 08.06.2020