Post

Replies

Boosts

Views

Activity

Propagate a @Published value from a Core Data ManagedContext
I have some code that has a long-running task inside of a .perform{} block. I'd like to be able to show the status of this long-running code in a Swift UI view by passing data through a @Published var. But .perform{} seems to prevent @Published from actually propagating to the view. Is there a way to get the view to update in the middle of this perform{} block? I've managed to boil my problem down to a playground that illustrates the issue . See the ????? comment. import SwiftUI import PlaygroundSupport import CoreData struct ContentView: View { @StateObject var contentModel = ContentModel() var body: some View { VStack { HStack { Text("Status:") Text(contentModel.status) } Spacer() Button("Do stuff.") { contentModel.updateStatus() } } Spacer() } } class ContentModel: ObservableObject { @Published var status = "foo" func updateStatus() { let managedObjectContext = PersistenceController.preview.container.viewContext // this perform is needed in the Real App™ to manage data fetch + output managedObjectContext.perform { // it doesn't matter that this is async DispatchQueue.main.async { let oldStatus = self.status // this status does not propagate into the @Published // until after the perform{} block finishes // (read: we don't see it show "X" in the UI) self.status = "X" // ????? how can I make this propagate the the view right away? // simulate a long-running (blocking) operation sleep(3) // cheap toggle if oldStatus == "foo" { self.status = "bar" } else { self.status = "foo" } } } } } class PersistenceController { static let shared = PersistenceController() let container: NSPersistentContainer static var preview: PersistenceController = { let result = PersistenceController(inMemory: true) let viewContext = result.container.viewContext return result }() init(inMemory: Bool = false) { let model = NSManagedObjectModel() container = NSPersistentContainer(name: "Example", managedObjectModel: model) container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy } } PlaygroundPage.current.setLiveView(ContentView())
2
0
903
Aug ’22