Issue #468
From onAppeear
Adds an action to perform when the view appears.
In theory, this should be triggered every time this view appears. But in practice, it is only called when it is pushed on navigation stack, not when we return to it.
So if user goes to a bookmark in a bookmark list, unbookmark an item and go back to the bookmark list, onAppear
is not called again and the list is not updated.
import SwiftUI
struct BookmarksView: View {
let service: Service
@State var items: [AnyItem]
@EnvironmentObject var storeContainer: StoreContainer
var body: some View {
List(items) { item in
makeItemRow(item: item)
.padding([.top, .bottom], 4)
}
.onAppear(perform: {
self.items = storeContainer.bookmarks(service: service).map({ AnyItem(item: $0) })
})
}
}
So instead of relying on UI state, we should rely on data state, by listening to onReceive
and update our local @State
struct BookmarksView: View {
let service: Service
@State var items: [AnyItem]
@EnvironmentObject var storeContainer: StoreContainer
var body: some View {
List(items) { item in
makeItemRow(item: item)
.padding([.top, .bottom], 4)
}
.onAppear(perform: {
self.reload()
})
.onReceive(storeContainer.objectWillChange, perform: { _ in
self.reload()
})
}
private func reload() {
self.items = storeContainer.bookmarks(service: service).map({ AnyItem(item: $0) })
}
}
Inside our ObservableObject
, we need to trigger changes notification
final class StoreContainer: ObservableObject {
let objectWillChange = PassthroughSubject<(), Never>()
func bookmark(item: ItemProtocol) {
defer {
objectWillChange.send(())
}
}
func unbookmark(item: ItemProtocol) {
defer {
objectWillChange.send(())
}
}
}
Updated at 2020-10-03 10:43:47