I have a list in ViewA which has 3 rows. ViewA is a grand-child of the main view(not sure if this info matters, but just providing since I don't know where the actual bug is. Here is how the stack is ContentView -> opens Main Menu View(MMV) -> select an item from MMV and it opens -> Settings View -> select an item from Settings and it opens ViewA).
When I click on a row in ViewA, another view should opens up let's say ViewB. However I am seeing ViewB instantiating 3 times i.e. I see ViewB appearing 3 times on the screen and then it stops at the last instance.
I am not sure why this is happening and what the actual bug is. Here is my code:
ViewA(MenuViewOptions):
struct MenuViewOptions: View {
@State var destination: MenuViewType?
var isActive: Binding<Bool> { Binding(get: { destination != nil }, set: { _ in destination = nil } ) }
var body: some View {
VStack {
List(SettingsOptions().menuViewSettingsOptions) { item in
NavigationLink(isActive: isActive, destination: {destination?.view} ) {
MenuViewOptionRowView(menuViewItem: item, destination: $destination)
}
}
}.navigationBarTitle("Settings")
}
}
MenuViewType code:
enum MenuViewType: Int, CaseIterable, Hashable {
case circularGrid = 0, regularList = 1, capsuleGrid = 2
@ViewBuilder var view: some View {
switch self {
case .circularGrid: MainMenuCircularGridViewNew()
case .regularList: MainMenuListView()
case .capsuleGrid: MainMenuCapsuleGridView()
}
}
}
SettingsOptions().menuViewSettingsOptions code:
struct SettingsOptions {
// View inside menu view settings
let menuViewSettingsOptions: [MenuViewSettingsItem] = [
MenuViewSettingsItem(id: 0, name: "Circular Grid", imageName: "circle.grid.2x2", isSelected: false),
MenuViewSettingsItem(id: 1, name: "List", imageName: "list.dash", isSelected: false),
MenuViewSettingsItem(id: 2, name: "Capsule Grid", imageName: "rectangle.grid.2x2", isSelected: false),
]
}
MenuViewOptionRowView code
struct MenuViewOptionRowView: View {
let menuViewItem: MenuViewSettingsItem
@ObservedObject var userSettingsStore = UserSettingsStore()
@Binding var destination: MenuViewType?
var body: some View {
HStack {
Image(systemName: menuViewItem.imageName)
.circularImageStyle(width: 15, height: 15, padding: 5, backgroundColor: Color(red: 34 / 255, green: 34 / 255, blue: 34 / 255), foregroundColor: Color(red: 23 / 255, green: 121 / 255, blue: 232 / 255))
Text(menuViewItem.name)
Spacer()
if menuViewItem.id == userSettingsStore.menuViewSelection {
Image(systemName: "checkmark").foregroundColor(Color(red: 23 / 255, green: 121 / 255, blue: 232 / 255))
}
}.onTapGesture {
userSettingsStore.menuViewSelection = self.menuViewItem.id
destination = MenuViewType(rawValue: self.menuViewItem.id)
}
}
}
Basically I am setting the destination in MenuViewOptionRowView and once it's set, isActive in MenuViewOptions becomes true and NavigationLink gets fired. I am seeing the row navigates to the correct view, but just that the view instantiates 3 times which I am not sure if it is because I have 3 rows in the list.
If you have any idea of what could be the issue, please do let me know. New to SwiftUI.
Thanks!
You set destination once, but with this you activate all links in List, because they are all bound to one isActive
.
With such code design I would propose the following solution: one destination - one link, destination is already set on tap, so... (code in question is not testable so just as-is)
List(SettingsOptions().menuViewSettingsOptions) { item in
MenuViewOptionRowView(menuViewItem: item, destination: $destination)
}
.background(
NavigationLink(isActive: isActive, destination: {destination?.view} ) {
EmptyView()
}
)