swift – Why can’t my watch app see data from my iOS Core Data app?


I’ve been following along with a Hacking with Swift tutorial where he makes an app that syncs data across iPhone, iPad and Mac versions of his app. All the syncing is handled by Core Data and Cloud Kit.

I’ve been trying to adapt what he did to my own app which has a companion watchOS app. I’m using NSPersistentCloudKitContainer

I’ve put the iOS app and the watchOS app in the same app group and I’m loading the shared app container with the correct app group identifier (my widget can see the data just fine), but the watch app can never see the data. The watch app doesn’t crash, it just doesn’t see anything to load, I get back an empty array of entities.

Can watch apps not use this method? Am I missing some key step?

Here’s the DataController class:

import CoreData
import SwiftUI

class DataController: ObservableObject {
let container: NSPersistentCloudKitContainer
private var saveTask: Task<Void, Error>?

static var preview: DataController = {
    let dataController = DataController(inMemory: true)
    return dataController
}()

private var sharedStoreURL: URL {
    let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.MyCo.MyApp1")!
    return container.appendingPathComponent("Model.sqlite")
}



static let model: NSManagedObjectModel = {
    guard let url = Bundle.main.url(forResource: "Model", withExtension: "momd") else {
        fatalError("Failed to locate model file.")
    }

    guard let managedObjectModel = NSManagedObjectModel(contentsOf: url) else {
        fatalError("Failed to load model file.")
    }

    return managedObjectModel
}()


init(inMemory: Bool = false) {
    container = NSPersistentCloudKitContainer(name: "Model", managedObjectModel: Self.model)
    
    if inMemory {
        container.persistentStoreDescriptions.first?.url = URL(filePath: "/dev/null")
    } else {
        container.persistentStoreDescriptions.first?.url = sharedStoreURL
    }
    
    container.viewContext.automaticallyMergesChangesFromParent = true
    container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
    
    container.persistentStoreDescriptions.first?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
    NotificationCenter.default.addObserver(forName: .NSPersistentStoreRemoteChange, object: container.persistentStoreCoordinator, queue: .main, using: remoteStoreChanged)
    
    container.loadPersistentStores { _, error in
        if let error {
            fatalError("Fatal error loading store: \(error.localizedDescription)")
        }
        
    }
}



func remoteStoreChanged(_ notification: Notification) {
    objectWillChange.send()
}


func save() {
    saveTask?.cancel()
    
    if container.viewContext.hasChanges {
        try? container.viewContext.save()
    }
}


func queueSave() {
    saveTask?.cancel()
    
    saveTask = Task { @MainActor in
        try await Task.sleep(for: .seconds(3))
        save()
    }
}


func delete(_ object: NSManagedObject) {
    objectWillChange.send()
    container.viewContext.delete(object)
    save()
}



private func delete(_ fetchRequest: NSFetchRequest<NSFetchRequestResult>) {
    let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
    batchDeleteRequest.resultType = .resultTypeObjectIDs
    
    if let delete = try? container.viewContext.execute(batchDeleteRequest) as? NSBatchDeleteResult {
        let changes = [NSDeletedObjectsKey: delete.result as? [NSManagedObjectID] ?? []]
        NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [container.viewContext])
    }
}


func getMyEntities() throws -> [MyEntity] {
    let request: NSFetchRequest<MyEntity> = MyEntity.fetchRequest()
    request.sortDescriptors = [NSSortDescriptor(keyPath: \MyEntity.name, ascending: true)]
   
    let entities = try container.viewContext.fetch(request)
   
    return entities
}

}

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img