Reputation: 239
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:
Upvotes: 2
Views: 1995
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