6

我有一个带有意图扩展目标的 SwiftUI 应用程序。我还有一个位于共享应用程序组的核心数据存储。

newBackgroundContext()Intents 扩展可以使用Shortcuts 应用程序成功地将数据写入商店。我的 SwiftUI 应用程序可以从应用程序组中读取数据,viewContext但只有当我强制退出应用程序并重新打开它时。

我想我需要一种方法让我的应用知道它已在不同的上下文中更新,但我不确定如何做到这一点?

我已经尝试context.automaticallyMergesChangesFromParent = true在应用程序委托中设置并在 SwiftUI 视图中添加context.refreshAllObjects()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()
}

斯威夫特用户界面视图

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")
}
4

2 回答 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 变量以填充我的视图中的字符串。

希望这会有所帮助。

于 2020-01-19T03:13:20.083 回答
-1
class Data: ObservableObject {

    @Published var dataToUpdate: Int 
}

struct UpdateView : View {

@EnvironmentObject data: Data


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

只需像您在此示例中看到的那样定义数据。然后在您的数据库更改时填充 dataToUpdate ......当然这只是一个简单的例子,只有一个 Int 值......

于 2019-12-18T14:29:28.473 回答