Reputation: 2387
I have a ForEach loop for my StudentStore
and only want to display them in my list if the isFavorite
field is true.
The problem is when I edit the value of isFavorite inside SecondView
, it goes back to ContentView
because of the if
statement inside ContentView
.
I want the list to update when I get back to ContentView
rather than updating it immediately causing it to go back to the original page.
When I was looking for a solution I came upon this:
Read this entire thread thinking you were asking if you could make a NavigationView conditionally hidden and thought, “That sounds like a mess...”
Source: https://www.reddit.com/r/SwiftUI/comments/e2wn09/make_navigationlink_conditional_based_on_bool/
Can someone also how to solve this problem and why conditionally hiding a NavigationView
is a bad idea?
Model
import SwiftUI
struct StudentItem: Identifiable {
var id = UUID()
var name: String
var isFavorite: Bool
init(name: String, isFavorite: Bool) {
self.name = name
self.isFavorite = isFavorite
}
}
class StudentStore: ObservableObject {
@Published var StudentStore: [StudentItem]
init(StudentStore: [StudentItem]){
self.StudentStore = StudentStore
}
}
Main view
struct ContentView: View {
@ObservedObject var studentStore = StudentStore(StudentStore: [StudentItem(name: "Stephen", isFavorite: true),
StudentItem(name: "Jay", isFavorite: true),
StudentItem(name: "Isaac", isFavorite: true),
StudentItem(name: "Talha", isFavorite: true),
StudentItem(name: "John", isFavorite: true),
StudentItem(name: "Matt", isFavorite: true),
StudentItem(name: "Leo", isFavorite: true)])
var body: some View {
NavigationView {
List {
ForEach(studentStore.StudentStore.indices, id: \.self) { index in
Group {
if self.studentStore.StudentStore[index].isFavorite == true {
NavigationLink(destination: SecondView(student: self.$studentStore.StudentStore[index])) {
HStack {
Text(self.studentStore.StudentStore[index].name)
Image(systemName: self.studentStore.StudentStore[index].isFavorite ? "star.fill" : "star")
}
}
}
}
}
}
}
}
}
Sub view
struct SecondView: View {
@Binding var student: StudentItem
var body: some View {
Button(action: {
self.student.isFavorite.toggle()
}) {
Image(systemName: student.isFavorite ? "star.fill" : "star")
}
}
}
Upvotes: 0
Views: 316
Reputation: 93
The problem makes sense, it's a Binded value. The Navigation to that person SecondView
technically no longer exists according to the Binding.
You could create a localized State
for SecondView
, set your Image and Button to work that that property, and then use onDisappear
to update the StudentItem
as you Navigate back.
struct SecondView: View {
@Binding var student: StudentItem
@State var isFavorite: Bool = true
var body: some View {
Button(action: {
self.isFavorite.toggle()
}) {
Image(systemName: self.isFavorite ? "star.fill" : "star")
}.onDisappear {
self.student.isFavorite = self.isFavorite
}
}
}
The above will work with the rest of your code.
As for not using an if
statement, I kind of get it. For me, I would want to iterate through the values I know I want to include. Not saying this is perfect, but you could filter the list before you go in, and then summon the Bindable reference to the StudentItem
to pass into SecondView
. Be sure to make StudentItem
Hashable
for this to work:
var body: some View {
NavigationView {
List {
ForEach(studentStore.StudentStore.filter({$0.isFavorite == true}), id: \.self) { student in
Group {
NavigationLink(destination: SecondView(student: self.$studentStore.StudentStore[self.studentStore.StudentStore.firstIndex(of: student)!])) {
HStack {
Text(student.name)
Image(systemName: student.isFavorite ? "star.fill" : "star")
}
}
}
}
}
}
}
Upvotes: 1