In my SwiftUI / iOS 15+ app, I have a toolbar displaying a button which is meant to toggle the "bookmarked" property of an "item" object. The item is passed in as a Binding, as shown here:
import SwiftUI
struct PageViewToolbar: ToolbarContent {
@Environment(\.managedObjectContext) var context
@Binding var item: Item //CoreData ManagedObject
var body: some ToolbarContent {
ToolbarItem(placement: .automatic) {
Toggle(isOn: self.$item.bookmarked) {
Image(systemName: "bookmark")
.symbolVariant(self.item.bookmarked ? .fill : .none)
} //Toggle
.toggleStyle(.button)
} //ToolbarItem
} //body
} //PageViewToolbar
The button is toggling and the bookmarked property on the item is being set accordingly, but item is a CoreData ManagedObject and so I need to trigger a context save whenever the property is changed. Is there a way to attach that logic to the Toggle button?
First of all item
is reference type so you must use @ObservedObject
rather than @Binding
to get notified about changes. Fortunately NSManagedObject
conforms to ObservableObject
by default.
Then add the .onChange
modifier to save the context when bookmarked
has changed.
struct PageViewToolbar: ToolbarContent {
@Environment(\.managedObjectContext) var context
@ObservedObject var item: Item
var body: some ToolbarContent {
ToolbarItem(placement: .automatic) {
Toggle(isOn: $item.bookmarked) {
Image(systemName: "bookmark")
.symbolVariant(item.bookmarked ? .fill : .none)
} //Toggle
.toggleStyle(.button)
.onChange(of: item.bookmarked) { _ in
try? context.save()
}
} //ToolbarItem
} //body
} //PageViewToolbar