Adam Carter
Adam Carter

Reputation: 4844

NSPersistentStoreCoordinator not created on a UIManagedDocument

I'm starting to learn about UIManagedDocument and its abilities. From what I understand of it its a form of database stored in a location in the documents directory.

Anyway, I'm trying to use it as a database, by storing data within its NSManagedObjectContext however, after a few seconds of creating the UIManagedDocument and saving data to its context (after I'm guessing timing out), the app crashes and it tells me there is no persistent store coordinator.

There doesn't seem to be much guidance on the Apple docs as to how to create a persistent store coordinator after creating the managed document.

How do I do this exactly?

Thanks!

Edit

Code I'm using:

NSURL *url = [[self iCloudDocumentsURL] URLByAppendingPathComponent:nameOfDocument];

NSMutableArray *books = [self.books mutableCopy];
[books addObject:url];

[self setBooks:books];

UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:url];

NSDictionary *options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
                           NSInferMappingModelAutomaticallyOption : @YES,
                           NSPersistentStoreUbiquitousContentNameKey : document.fileURL.lastPathComponent,
                           NSPersistentStoreUbiquitousContentURLKey : [self iCloudCoreDataLogFilesURL] };
[document setPersistentStoreOptions:options];

if (document.documentState == UIDocumentStateClosed) {
    [document openWithCompletionHandler:^(BOOL success) {
        Book *book = [Book newBookWithTitle:bookTitle
                     inManagedObjectContext:document.managedObjectContext];

        [document updateChangeCount:UIDocumentChangeDone];
    }];
}

Update

After performing this code on a background thread. My app still logs 'NO' for the success on the completion handler after opening the document. However, my app does not crash, instead I get the following log:

2013-04-23 00:01:08.381 Notable[193:4b0b] -[_PFUbiquityRecordsImporter rollResponseOperation:encounteredAnError:whileTryingToAdoptBaseline:](1545): CoreData: Ubiquity:  <PFUbiquityBaselineRollResponseOperation: 0x1fa561d0> localPeerID: mobile.2DDB96C5-A317-5BE5-8F29-9F5E6681A27A, storeName: A-B893A0AB-B764-42F1-9402-38790DCEF96B, modelVersionHash: NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=
    ubiquityRootLocation: <PFUbiquityLocation: 0x1e59b790>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs

Encountered an error while trying to respond to the roll of baseline: <PFUbiquityBaseline: 0x1e54deb0>(0)
    permanentLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip
    safeLocation: <PFUbiquityLocation: 0x1f8eb1b0>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/mobile.2DDB96C5-A317-5BE5-8F29-9F5E6681A27A
    currentLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip

    storeName: A-B893A0AB-B764-42F1-9402-38790DCEF96B
    modelVersionHash: NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=
    baselineArchiveLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip

Error: Error Domain=NSCocoaErrorDomain Code=134310 "The operation couldn’t be completed. (Cocoa error 134310.)" UserInfo=0x1f8d2ae0 {baseline=<PFUbiquityBaseline: 0x1e54deb0>(0)
    permanentLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip
    safeLocation: <PFUbiquityLocation: 0x1f8eb1b0>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/mobile.2DDB96C5-A317-5BE5-8F29-9F5E6681A27A
    currentLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip

    storeName: A-B893A0AB-B764-42F1-9402-38790DCEF96B
    modelVersionHash: NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=
    baselineArchiveLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip
, localStoreKV=<PFUbiquityKnowledgeVector: 0x1f8220c0> ()}
userInfo: {
    baseline = "<PFUbiquityBaseline: 0x1e54deb0>(0)\n\tpermanentLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip\n\tsafeLocation: <PFUbiquityLocation: 0x1f8eb1b0>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/mobile.2DDB96C5-A317-5BE5-8F29-9F5E6681A27A\n\tcurrentLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip\n\n\tstoreName: A-B893A0AB-B764-42F1-9402-38790DCEF96B\n\tmodelVersionHash: NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=\n\tbaselineArchiveLocation: <PFUbiquityLocation: 0x1f8e7120>: /private/var/mobile/Library/Mobile Documents/my~app~identifier/Logs/.baseline/A-B893A0AB-B764-42F1-9402-38790DCEF96B/NK3BysbustJxxyi2O8bX8eof15YimkUnegxqX6HDkas=/baseline.zip\n";
    localStoreKV = "<PFUbiquityKnowledgeVector: 0x1f8220c0> ()";
}

This method also creates a 'DocumentMetaData.plist' (which I believe is necessary according to this files mention in the CS193P video I mentioned in a comment) instead of a file entitled 'persistentStore'.

Upvotes: 1

Views: 672

Answers (3)

Duncan Groenewald
Duncan Groenewald

Reputation: 8988

Not sure if you ever fixed this Adam but you persistentStore should not be in the Cloud. Always create the uiManagedDocument in the local store and just set the iCloud options for addPersistentStore. CoreData will provide an immediate store for your app to use while it builds the real version and gets any data from iCloud if there is any. Once done it will switch you to the ICloud connected store which is also local. Only the transactions logs are posted to iCloud but that's done under the covers for you.

Upvotes: 1

Tom Harrington
Tom Harrington

Reputation: 70946

You're not supposed to create it yourself when using UIManagedDocument-- that happens for you. However it's not that reliable in practice. Internally, UIManagedDocument sets up the persistent store and the persistent store coordinator. But that doesn't happen until the underlying iCloud code finishes getting its act together, talking to the server, downloading any new data, etc. In the meantime, you can't save changes, because until this process finishes there's nowhere to save those changes.

Also, sometimes iCloud fails to get its act together, for no reason that's under your control.

You probably need to check the success value in your open completion handler. If it's NO, you're kind of stuck. When iCloud flakes out there's no recovery path except sometimes if you're lucky you can just try again a few times until it works. File bugs, please, we need Apple to fix this.

Upvotes: 1

Hal Mueller
Hal Mueller

Reputation: 7646

There's sample code in the UIDocument Class Reference, and also in the Core Data Programming Guide. You can also see an example of the Core Data stack setup by creating a Core Data based project using the Master-Detail template.

If this is your first experience with Core Data, I suggest you work through one of the books on the subject, either Core Data for iOS, by Tim Isted and Tom Harrington, or Core Data (2nd edition): Data Storage and Management for iOS, OS X, and iCloud, by Marcus Zarra.

I see a couple of things that look odd:

  • Does [self iCloudDocumentsURL] point to the local file system?

  • Why is the URL being inserted into the array of books?

  • Test the success variable in your block before assuming that the open succeeded.

Even in iOS 6.x, iCloud Core Data is not ready for prime time. It's certainly not something a new iOS dev wants to tackle. See what the very bright people at Black Pixel had to say about it with respect to one of their own products: http://blackpixel.com/blog/2013/03/the-return-of-netnewswire.html.

Upvotes: 0

Related Questions