I have managed to get CoreData with CloudKit working with the new NSPersistentCloudKitContainer on the iOS version of my app and got it to automatically sync while the app is running. However, when I went to set things up on the watchOS app, I noticed that a sync will only occur if I force close and reopen the watch app.
import Foundation
import CoreData
class DataManager : NSObject {
static let shared = DataManager()
#if os(watchOS)
let transactionAuthorName = "watchOSApp"
#else
let transactionAuthorName = "iOSApp"
#endif
override private init() {
super.init()
}
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentCloudKitContainer(name: "Model")
let cloudStoreUrl = applicationDocumentDirectory()!.appendingPathComponent("product.sqlite")
let cloudStoreDescription = NSPersistentStoreDescription(url: cloudStoreUrl)
cloudStoreDescription.shouldInferMappingModelAutomatically = true
cloudStoreDescription.shouldMigrateStoreAutomatically = true
cloudStoreDescription.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier:"iCloud.com.company.product")
container.persistentStoreDescriptions = [cloudStoreDescription]
container.loadPersistentStores(completionHandler: { storeDescription, error in
if let error = error as NSError? {
print("Error loading store. \(error)")
}
})
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
container.viewContext.automaticallyMergesChangesFromParent = true
try? container.viewContext.setQueryGenerationFrom(.current)
container.viewContext.transactionAuthor = transactionAuthorName
return container
}()
}
// MARK: - Core Data
extension DataManager {
func applicationDocumentDirectory() -> URL? {
return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:"group.shiningdevelopers.h2o")
}
func managedObjectContext() -> NSManagedObjectContext {
return persistentContainer.viewContext
}
func reset() {
managedObjectContext().reset()
}
func saveContext () {
let context = managedObjectContext()
if context.hasChanges {
do {
try context.save()
} catch let error as NSError {
// Replace this implementation with code to handle the error appropriately.
// Log this error for now to be able to glean more information
print("Could not save. \(error), \(error.userInfo)")
}
}
}
}
The following scenarios work - User has both the watchOS app and iOS app running - User makes a change to the data on the watch app - The change is reflected on the iOS app - User has only the iOS app running - User makes a change to the data on the iOS app - The user opens the watchOS app from terminated - The changes are reflected on the watchOS app
The following scenario does not work - User has the watchOS app running and the iOS app running - User makes a change to the data on the iOS app - No change ever makes it through to the watchOS app, even after waiting a long time - Only if I force close the app and restart does a sync occur
In the cases were a sync is successful I see the following logs correctly:
CoreData: debug: CoreData+CloudKit:
-[PFCloudKitImporterZoneChangedWorkItem newMirroringResultByApplyingAccumulatedChanges:]_block_invoke_2(243): <PFCloudKitImporterZoneChangedWorkItem: 0x16530fb0> { ( "<CKRecordZoneID: 0x1656a920; zoneName=com.apple.coredata.cloudkit.zone, ownerName=__defaultOwner__>" ) } - Importing updated records: ( "<CKRecord: 0x16526280; recordType=CD_LogEntry, values={\n "CD_day" = 15;\n "CD_entityName" = LogEntry;\n "CD_glassesGoal" = 8;\n "CD_glassesLogged" = 13;\n "CD_lastModified" = "2019-09-15 18:56:08 +0000";\n "CD_month" = 9;\n "CD_year" = 2019;\n}, recordChangeTag=7d, recordID=2180D6A3-ACFC-4421-8CAF-6EE288DAAC2E:(com.apple.coredata.cloudkit.zone:defaultOwner)>" ) Deleted RecordIDs: {
}
In the last scenario, however, I don't see any logs, it's completely quiet. I am sharing the same CoreData/CloudKit code in both the iOS and watchOS versions of the app. I am also using a NSFetchedResultsController to make sure my UI stays up to date and it seems to be working on the iOS app but not the watchOS app. Not sure if there was some step that I had missed when setting up the watch extension.
Has anyone gotten syncing to watchOS to work? Any help would be appreciated.