32

I have been following these instructions to integrate iCloud support with CoreData and I am getting some errors.

I have this in my 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;
}

In another view controller I create an instance of my AppDelegate, create an object and call [appDelegate saveContext]; This is where the app crashes. This has always worked perfectly (up until now, adding iCloud support).

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

So it crashes at this method, and the console gives me this message:

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

What can I do next?

Edit

Console log below:

Upon launching the app, I get:

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!

Followed up when the app crashes with:

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) 
halfer
  • 19,824
  • 17
  • 99
  • 186
Josh Kahane
  • 16,765
  • 45
  • 140
  • 253

9 Answers9

44

I had the same problem and my solution was to delete the application and install it again because of modifications in database.

Montag451
  • 1,168
  • 3
  • 14
  • 30
edzio27
  • 4,126
  • 7
  • 33
  • 48
  • You'd think by now I'd remember to do this. Thanks for quickly reminding me! – Jacob Kranz Feb 26 '14 at 06:57
  • 13
    This only works if you have not lunched your app into app store. Otherwise it will resolve into crashing app for all users that downloaded previous version and updated it with your new version. – Eugene Pavlov Jul 12 '17 at 19:16
30

You are probably calling persistentStoreCoordinator method from two (or more) different threads. Either directly or indirectly.

As written that method is not thread safe.

It may be you have other methods with the same problem. Typically managedObjectContext exists and is written in a similar way.

There are two ways to solve this problem:

  • use @synchronize to make those methods thread safe
  • move the initialization code out of them and into an init method and modify them to assert/except if the ivar is nil

The second thing that you may also be doing wrong is to modify the context (for example adding new managed objects to it) and then trying to save it, before the store has been initialized.

To solve this make sure you do either one of the following:

  • you do not add any managed object to the context unless you know there is already at least one managed object in it (implying the store is loaded)
  • if you need to add a managed object to the context without checking that there's one already (for example after you initially create the empty store), make sure the store has been initialized already (for example do it when you get the RefetchAllDatabaseData notification and you notice the database is empty).
Joseph at SwiftOtter
  • 4,276
  • 5
  • 37
  • 55
Analog File
  • 5,280
  • 20
  • 23
  • 1
    I am facing same problem like Josh Kahane but please tell me how can I use "synchronize" in persistentStoreCoordinator? plz reply me – Nikunj Jadav Oct 31 '13 at 07:38
  • For me: the second one is more likely: because `PSContainer.loadPersistentStores { ... ` is finished only when it calls that closure! so returning immediately may cause you to use a store that is not yet loaded (only by a fraction on second) – Siempay Nov 16 '19 at 09:05
  • @Nikunj Jadav, have you found any solution. – Naresh Jan 25 '23 at 06:33
5

I solved it by removing the app from simulator and run it again. I guess it happens because the previous version of app does not have core data in it.

surga
  • 1,436
  • 21
  • 25
1

Resolved by moving the let moc = DataController().managedObjectContext to the top of the class rather than leaving inside of the func seedPerson()

Arkelyan
  • 250
  • 4
  • 14
1

I saw this error during testing when I spun up some temporary NSManagedObjectContexts without hanging on to them anywhere - the context would get deallocated out from under me at random by ARC.

What wound up working was to hold a reference to the MOC on the tests and reset it for each test.

Not sure how relevant this is to non-test circumstances, but particularly if you're using child/sibling contexts, it's worth making sure they're actually still there. :P

DesignatedNerd
  • 2,514
  • 1
  • 23
  • 46
1

I had the same problem. The reason I was getting the error was because I had made some minor changes in my CoreData Entity schema( Basically I added 2-3 new attributes). And I forgot about it as it does not give any errors until we run it. So what happens is, the app which was running earlier already had the persistent store with the previous schema. So the new schema is pointing to the same store. That is why we het the error when we run it as we try to access the new attributes.

Solution : Delete the app from the device/simulator. And reinstall it. (The new build will have the new schema and hence won't crash.)

Priyanka
  • 442
  • 1
  • 5
  • 13
1

For me, I found addPersistentStoreWithType always returns nil in my case. So the persistent store wasn't created successfully. Then, I print the storeURL

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

This is a directory in which we can't write data. So I checked my code and found a silly mistake. enter image description here

  • I should use NSDocumentDirectory instead of NSDocumentationDirectory. Code completion in Xcode offers the documentation directory before the document directory enum.

  • When I used NSDocumentationDirectory, NSPersistentStoreCoordinator always tried to create the persist store in .../Library/Documentation/my-database.sqlite, which is an invalid path.

  • Instead, the correct path should be .../Documents/BeeLocation.sqlite.
RY_ Zheng
  • 3,041
  • 29
  • 36
0

Update re. XCODE 4.6.3 and MACOSX 10.9.5:

To solve the problem I removed the app directory related to the product in xcode derived data location:

rm -rd /Users//Library/Developer/Xcode/DerivedData/. Apparently the data gets messed up after playing with the object model.

mdohmen
  • 11
  • 2
0

I have also stuck with this problem. For that I have first check core data migration code Since the code was correct in my case, I have delete my app from device and reinstall it. And it works.

bittu
  • 683
  • 7
  • 24