当后台扩展更新核心数据存储时,如何刷新我的SwiftUI视图?

6
我有一个SwiftUI应用程序,带有一个意图扩展目标。 我还有一个位于共享应用组中的核心数据存储。
使用Shortcuts应用程序中的newBackgroundContext(),意图扩展可以成功地将数据写入存储。 我的SwiftUI应用程序可以在viewContext中从应用组读取数据,但只有当我强制退出应用程序并重新打开它时才能读取。
我认为我需要一种方法让我的应用程序知道它已在不同的上下文中更新,但我不确定如何做到这一点?
我尝试在应用程序委托中设置context.automaticallyMergesChangesFromParent = true,并将context.refreshAllObjects()添加到SwiftUI视图中的onAppear,但似乎没有任何区别。 mergeChanges(fromContextDidSave:)似乎很有前途,但我不确定如何获取通知。
我对Core Data很陌生,非常困惑,因此任何指向正确方向的指针都将是极好的,谢谢!
以下是我当前代码的精简版本: 应用委托
 lazy var persistentContainer: NSCustomPersistentContainer = {
        let container = NSCustomPersistentContainer(name: "exampleContainerName")
        container.loadPersistentStores { description, error in
            if let error = error {
                print("error loading persistent core data store")
            }
        }
        return container
    }()

    func saveContext () {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                print("error saving core data context")
            }
        }
    }

class NSCustomPersistentContainer: NSPersistentContainer {
    override open class func defaultDirectoryURL() -> URL {
        var storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "exampleAppGroupName")
        storeURL = storeURL?.appendingPathComponent("exampleContainerName")
        return storeURL!
    }
}

场景代理

guard let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext else {
            fatalError("Unable to read managed object context.")
}

if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: ExampleView.environment(\.managedObjectContext, context))
            self.window = window
            window.makeKeyAndVisible()
}

Swift UI 视图

import SwiftUI
import CoreData

struct ExampleView: View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(
        entity: ExampleEntityName.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \ExampleEntityName.date, ascending: false),
        ]
    ) var items: FetchedResults<ExampleEntityName>

    var body: some View {
        VStack {
            List(items, id: \.self) { item in
                Text("\(item.name)")
            }
        }
    }
}

意图扩展

class NSCustomPersistentContainer: NSPersistentContainer {
    override open class func defaultDirectoryURL() -> URL {
        var storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "exampleContainerName")
        storeURL = storeURL?.appendingPathComponent("exampleAppGroupName")
        return storeURL!
     }
}

let persistentContainer: NSCustomPersistentContainer = {
    let container = NSCustomPersistentContainer(name: "exampleContainerName")
    container.loadPersistentStores { description, error in
        if let error = error {
            print("error loading persistent core data store: \(error)")
        }
    }
    return container
}()

let context = persistentContainer.newBackgroundContext()

let entity = NSEntityDescription.entity(forEntityName: "ExampleEntityName", in: context)
let newEntry = NSManagedObject(entity: entity!, insertInto: context)
newEntry.setValue(Date(), forKey: "date")
newEntry.setValue("Hello World", forKey: "name")

do {
    try context.save()
} catch {
    print("Failed saving")
}

请查看此链接 https://dev59.com/AVMH5IYBdhLWcg3w1Dr0#58530246 - simibac
2个回答

1

不知道你是否已经找到答案,但我在使用UserDefaults和共享应用程序组中的意图扩展时遇到了类似的问题。最终对我有用的是在SceneDelegate中添加一个调用以下方法来加载项目:

func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
        SiriResponseManager.shared.grabUD()
    }

在我的例子中,我使用了一个单例来存储从UserDefaults加载项的方法。这个单例类是一个ObservableObject。在我的第一个加载视图(在我的情况下是ContentView)中,我将ObservedObject变量分配给我的单例类,并检索我的单例中的@State变量以填充视图中的字符串。
希望这可以帮助你。

-1
class Data: ObservableObject {

    @Published var dataToUpdate: Int 
}

struct UpdateView : View {

@EnvironmentObject data: Data


   ...body ... {
     // use data.dataToUpdate here
  }
}

只需像此示例中所示一样定义数据。然后在数据库更改时填充dataToUpdate…当然,这只是一个仅具有Int值的简化示例...


请评论一下,如果您要投下一个答案,这样回答的人就知道他们的答案有什么问题,以及未来的读者。 - dbDev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接