CloudKit CoreData not syncing on WatchOS

I have a watchOS extension that I'm trying to sync to their iPhone using CoreData and CloudKit, but it doesn't seem to want to sync.

I've tried a few solutions (CloudKit + CoreData on iOS and watchOS sync not working, Core data + CloudKit - sharing between iOS and watchOS companion app), but it's still not syncing.

Here's my shared (it's loading in both targets) persistence code:

Code Block import CoreDatastruct PersistenceController {    static let shared = PersistenceController()    static var preview: PersistenceController = {        let result = PersistenceController(inMemory: true)        return result    }()    let container: NSPersistentCloudKitContainer    init(inMemory: Bool = false) {        container = NSPersistentCloudKitContainer(name: "My-app")        if inMemory {            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")        }        let description = container.persistentStoreDescriptions.first                description?.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.com.mydomain.my-app")         container.loadPersistentStores(completionHandler: { (storeDescription, error) in            if let error = error as NSError? {                print("Unresolved error \(error), \(error.userInfo)")            }        })        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy        container.viewContext.automaticallyMergesChangesFromParent = true    }}


Should I have a different code for the watch? Right now both targets share all the files.

Both targets share the same xcdatamodeld file. I used to have all the ManagedObject classes automatically generated (Codegen: Class Definition), but someone suggested manually generating them, but that didn't seem to change anything. Maybe the classes need to be different for each target (but what should be different)?

Both targets have iCloud and background notifications enabled.

I don't know if this matters, but I'm using SwiftUI. Here's the view model and the relevant code that loads the data (same file for both targets):


Code Block import Foundationimport CoreDataimport SwiftUIfinal class ProjectListViewModel : ObservableObject {    private var viewContext : NSManagedObjectContext    @Published var settings : Settings?    @Published var coreDataHasError = false    @Published var projects : [Project]        init(viewContext : NSManagedObjectContext, settings : Settings? = nil) {        self.projects = [Project]()         self.viewContext = viewContext        self.settings = settings        if settings != nil {            updateList()        }    }               func updateList() {        var orderBy : NSSortDescriptor = NSSortDescriptor(keyPath: \Project.dateModified, ascending: false)        if settings != nil {            switch settings!.orderBy {            case Settings.OrderBy.dateCreated.rawValue:                orderBy = NSSortDescriptor(keyPath: \Project.dateCreated, ascending: false)            case Settings.OrderBy.alphabetical.rawValue:                orderBy = NSSortDescriptor(keyPath: \Project.name, ascending: true)            default:                orderBy = NSSortDescriptor(keyPath: \Project.dateModified, ascending: false)            }                    }        let request : NSFetchRequest<Project>  = Project.fetchRequest()        request.predicate = NSPredicate(format: "status == %d", Project.ProjectStatus.active.rawValue)        request.sortDescriptors = [orderBy]        projects = try! viewContext.fetch(request)    }    }

And the view (this one is only used by the watch):

Code Block import SwiftUIimport CoreDatastruct ProjectListView: View {    @ObservedObject var viewModel : ProjectListViewModel    @ObservedObject var settings : Settings    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>    @Environment(\.managedObjectContext) private var viewContext        init(viewContext: NSManagedObjectContext, settings: Settings) {        self.viewModel = ProjectListViewModel(viewContext: viewContext, settings: settings)        self.settings = settings    }        var body: some View {        if quickCountProject.count == 0 {            viewModel.addScratchProject()        }                return                        ScrollView {                VStack {                    if viewModel.projects.count >= 1 {                    ZStack {                                                VStack {                            Text(NSLocalizedString("Title", comment: "Page title"))                                .TitleStyle()                            List {                                          ForEach(viewModel.projects) { project in                                    NavigationLink(destination:                                                    ProjectView(project: project, settings: settings, viewModel: ProjectListViewModel(viewContext: viewContext), viewContext: viewContext)                                                    .environmentObject(self.settings)                                                    .environment(\.managedObjectContext, viewContext))                                    {                                        HStack {                                            Image(systemName: "plus.app.fill").foregroundColor(.main).imageScale(.large)                                            Text(project.name ?? "").font(.headline).padding(.bottom, 5).padding(.top, 5)                                                                                    }                                        .accessibilityHint(Text(NSLocalizedString("View project details", comment: "")))                                    }                                }                                                                .listRowBackground(Color.lightGray)                                .padding(0)                            }                            .frame(minHeight: (45 * CGFloat(viewModel.projects.count)))                        }                        .padding(0)                                            }                    } else {                        Text(NSLocalizedString("To start, add a new project on you phone or iPad. Or use the button below to do a quick count.", comment: ""))                            .fixedSize(horizontal: false, vertical: true)                    }                }                            }             .onAppear(perform: {                viewModel.updateList()            })    }}


I’m not sure if you resolved this yourself in the end, but I was experiencing a similar issue with roughly the same setup (Core Data, CloudKit, and SwiftUI): my iOS changes were syncing with CloudKit, but nothing seemed to change on watchOS.

I ended up changing the Core Data codegen for my model(s) from “Class Definition” to “Manual/None” in Xcode’s inspector. I then navigated to “Editor → Create NSManagedObject Subclass…” to create the data model classes, resolved build errors, and committed the changes.

It’s a shame that the automatically generated class definitions don’t seem to work as expected; I hope this solution works for you!

CloudKit CoreData not syncing on WatchOS
 
 
Q