0

I'm attempting to set up CoreData/CloudKit on a WatchOS application using NSPersistentCloudKitContainer. However, after calling container.loadPersistentStores, the viewContext.persistentStoreCoordinator field appears to still be nil.

Here are some code samples:

Persistence.swift

struct PersistenceController {
    static let shared = PersistenceController()
    let container: NSPersistentCloudKitContainer
    init() {
        container = NSPersistentCloudKitContainer(name: "Test")
        guard let description = container.persistentStoreDescriptions.first else {
            fatalError("Could not retrieve a persistent store description.")
        }
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })

    }
}

MainApp.swift

@main
struct EventLoggerApp: App {
    let persistenceController = PersistenceController.shared

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.managedObjectContext, persistenceController.container.viewContext)
        }
    }
}

ContentView.swift

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext
    func createRecord() {
        print(viewContext.persistentStoreCoordinator) // this is nil
        let sensorReadingDescription = NSEntityDescription.entity(forEntityName: "SensorReading", in: viewContext)! // this crashes
    }
}

The error I'm crashing with is:

2020-12-12 11:56:32.205433-0800 EventLoggerWatch WatchKit Extension[400:541990] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSPersistentStoreCoordinator for searching for entity name 'Test''
*** First throw call stack:
(0x1f4bb7dc 0x1edc9c04 0x23d68a44 0x174d34 0x174378 0x22fa9d6c 0x231422e0 0x23256ebc 0x22cb86a8 0x23256ed8 0x23256ebc 0x2327a6a4 0x2330f2dc 0x2324cdac 0x2324b6f4 0x2324b75c 0x2324bd20 0x4076df2c 0x40bd9f44 0x40763d70 0x40763e80 0x40763ce8 0x40b986cc 0x40b75abc 0x40becf04 0x40be59b4 0x1f43c4ec 0x1f43c3ec 0x1f43b74c 0x1f435dac 0x1f435574 0x235f94c0 0x40b580f8 0x40b5d5f8 0x350d9b68 0x1eed893c)
libc++abi.dylib: terminating with uncaught exception of type NSException

Please let me know if I can provide any more helpful context, and thanks in advance for the guidance!

Peter Lu
  • 157
  • 2
  • 11
  • `loadPersistentStores` is an asynchronous method and while a normal disk based store might be set to `shouldAddStoreAsynchronously = false` by default I wouldn’t bet on `NSPersistentCloudKitContainer` playing the same way. Check your sequencing with a couple of prints. – Warren Burton Dec 12 '20 at 20:29
  • Thanks for the comment, Warren. I am observing that the prints in the `loadPersistentStores` `completionHandler` aren't showing up. Where can I pass the `shouldAddStoreAsynchronously` flag? – Peter Lu Dec 12 '20 at 20:35
  • It looks like `shouldAddStoreAsynchronously` is a flag on the `NSPersistentStoreCoordinator` object, but I'm not directly creating that object, as far as I can tell. https://developer.apple.com/documentation/coredata/nspersistentstoredescription/1640599-shouldaddstoreasynchronously – Peter Lu Dec 12 '20 at 20:41
  • It’s a property on `NSPersistentStoreDescription` which you do recover but don’t use before you load the store You can mutate that description. – Warren Burton Dec 12 '20 at 21:22
  • Got it! I just tried adding the line `description.shouldAddStoreAsynchronously = false` before `loadPersistentStores`, which resulted in the same error. Does that fit what you were thinking to change? – Peter Lu Dec 12 '20 at 21:41
  • [This gist](https://gist.github.com/kharrison/0d19af0729ae324b8243a738844f8245) helped me a lot setting up my `NSPersistentCloudKitContainer`. Furthermore, instead of using a wrapper, I subclassed the container, as explained by Apple [here](https://developer.apple.com/documentation/coredata/setting_up_a_core_data_stack). Maybe it helps you. – koen Dec 16 '20 at 18:52

1 Answers1

-1

Upon further investigation, I'm not sure this question is valid. I think the code listed above was only running for the phone target, and not the watch. There are potentially issues with the watch as well, but I will work on getting the phone working first, as the issues are probably there. Thanks to all who helped out here!

Peter Lu
  • 157
  • 2
  • 11