Reputation: 24874
I have a dictionary that stores string -> bool, in my view, I wrap this dictionary around a Binding<Bool>
to be able to store the states of each NavigationLink
in order to later be able to programmatically navigate. Now, this works the first time, Page 1 -> Page 2 -> Page 3, but when you hit back to Page 2, the navigation stops working.
I have checked that the values of isLinkActive
dictionary do correctly get updated when NavigationLink
is tapped, however, NavigationLink
does not get activated.
import SwiftUI
class ContentViewModel: ObservableObject {
@Published var isLinkActive:[String: Bool] = [:]
}
struct ContentView: View {
@ObservedObject var contentViewModel = ContentViewModel()
var page3: some View {
Text("Page 3")
}
@State var data = ["1", "2", "3"]
func binding(chatId: String) -> Binding<Bool> {
return .init(get: { () -> Bool in
return self.contentViewModel.isLinkActive[chatId, default: false]
}) { (value) in
self.contentViewModel.isLinkActive[chatId] = value
}
}
var page2: some View {
return
List(data, id: \.self) { data in
NavigationLink(destination: self.page3, isActive: self.binding(chatId: data)) {
Text("Page \(data) Link")
}
}
}
var body: some View {
return NavigationView() {
VStack {
Text("Page 1")
NavigationLink(destination: page2) {
Text("Page 2 Link")
}
}
}
}
}
Upvotes: 2
Views: 1437
Reputation: 9915
There's nothing wrong with the logic of your code. The only issue is that SwiftUI doesn't redraw page2
as it only redraws the var body
during an onAppear
, and this view is not in context. The way to force refresh is thus to make page2
a body variable.
struct ContentView: View {
var body: some View {
return NavigationView() {
VStack {
Text("Page 1")
NavigationLink(destination: ContentViewTwo()) {
Text("Page 2 Link")
}
}
}
}
}
struct ContentViewTwo: View {
@ObservedObject var contentViewModel = ContentViewModel()
var page3: some View {
Text("Page 3")
}
@State var data = ["1", "2", "3"]
func binding(chatId: String) -> Binding<Bool> {
return .init(get: { () -> Bool in
return self.contentViewModel.isLinkActive[chatId, default: false]
}) { (value) in
self.contentViewModel.isLinkActive[chatId] = value
}
}
var body: some View {
return
List(data, id: \.self) { data in
NavigationLink(destination: self.page3, isActive: self.binding(chatId: data)) {
Text("Page \(data) Link")
}
}
}
}
Upvotes: 1