![](/img/trans.png)
[英]SwiftUI - How do I know when the back button of a navigation view has been clicked?
[英]How do I refresh my SwiftUI view when my core data store has been updated from a background extension?
我有一个带有意图扩展目标的 SwiftUI 应用程序。 我还有一个位于共享应用程序组的核心数据存储。
Intents 扩展可以使用 Shortcuts 应用程序中的newBackgroundContext()
成功地将数据写入存储。 我的viewContext
应用程序可以从 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()
}
Swift 用户界面视图
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")
}
不知道您是否找到了答案,但我在共享应用程序组中使用 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()
}
在我的示例中,我使用的是 singleton,其中包含从 UserDefaults 加载项目的方法。 这个 singleton class 是一个 ObservableObject。 在我加载的第一个视图中(在我的情况下为 ContentView),我将 ObservedObject 变量分配给我的 singleton class 并检索我的 singleton 中的 @State 变量以填充我的视图中的字符串
希望这会有所帮助。
class Data: ObservableObject {
@Published var dataToUpdate: Int
}
struct UpdateView : View {
@EnvironmentObject data: Data
...body ... {
// use data.dataToUpdate here
}
}
只需像您在此示例中看到的那样定义数据。 然后在您的数据库更改时填充 dataToUpdate ......当然这只是一个简单的例子,只有一个 Int 值......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.