簡體   English   中英

當我的核心數據存儲已從后台擴展更新時,如何刷新我的 SwiftUI 視圖?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM