Heimdallr
Heimdallr

Reputation: 239

First item in a List is always selected

I have a list of items, I want to make it possible to navigate to the details view. However, the first element in the list is always passed to this view, what could be the problem?

struct ContentView: View {
    var array: [Object] = [Object(id: .init(),property: 1),Object(id: .init(),property: 2),Object(id: .init(),property: 3)]
    
    @State var showAlert = false
    @State var showDetailsView = false
    
    
    var body: some View {
        NavigationView{
            List{
                ForEach(array){ item in
                    VStack{
                        Text(String(item.property))
                    }.onTapGesture(){ self.showAlert.toggle()}
                    .alert(isPresented: $showAlert){
                        Alert(title: Text("show details view?"), message: Text(""),
                              primaryButton: .default (Text("Show")) {
                                showDetailsView.toggle()
                              },
                              secondaryButton: .cancel()
                        )
                    }
                    .fullScreenCover(isPresented: $showDetailsView){ DetailsView(property: item.property) }
                }
            }
        }
    }
}

struct Object: Identifiable {
    let id: UUID
    var property: Int
}

struct DetailsView: View {
    var property: Int?
    
    var body: some View {
        Text(String(property!))
    }
}

I will get this result regardless of which item in the list I select:

listdatails view

Upvotes: 2

Views: 1995

Answers (1)

Asperi
Asperi

Reputation: 258057

In this scenario we can pass clicked item like baton from ForEach to Alert to FullScreen to Details. And, of course, we should move corresponding modifiers out of cycle, they don't need to be applied to each row.

Here is a modified code. Tested with Xcode 12.1 / iOS 14.1.

struct ContentView: View {
    var array: [Object] = [Object(id: .init(),property: 1),Object(id: .init(),property: 2),Object(id: .init(),property: 3)]
    
    @State var alertItem: Object?
    @State var selectedItem: Object?
    
    
    var body: some View {
        NavigationView{
            List{
                ForEach(array){ item in
                    VStack{
                        Text(String(item.property))
                    }.onTapGesture(){ self.alertItem = item}
                }
            }
              .alert(item: $alertItem) { item in
                    Alert(title: Text("show details view?"), message: Text(""),
                            primaryButton: .default (Text("Show")) {
                              selectedItem = item
                            },
                            secondaryButton: .cancel()
                    )
              }
              .fullScreenCover(item: $selectedItem){ DetailsView(property: $0.property) }
        }
    }
}

Upvotes: 4

Related Questions