I have a list of items and when user click on it, I need to show some content in .popover()
.
Model:
struct Item: Identifiable {
var id: String {
UUID().uuidString
}
var name: String?
var addr: String?
init(name: String? = nil, addr: String? = nil) {
self.name = name
self.addr = addr
}
}
View:
struct ContentView: View {
let arr = [
Item(name: "Roman", addr: "Address of Roman"),
Item(name: "Alexa", addr: "Address of Alexa"),
]
@State private var selection: Item?
var body: some View {
VStack {
List {
ForEach(arr) { item in
Text(item.name!)
.id(item.name!)
.onTapGesture {
selection = item
print("selection: \(item.name ?? "")")
}
.popover(item: $selection) { item in
Text(item.addr ?? "")
}
}
}
}
}
When user click on the name
. The popover is not showing up.
If there is only one item in the list, the popover is showing as expected(like below image).
Why the popover is not working as expected with List of items?
Is this a bug in SwiftUI?
The issue is because you are assigning a single binding to multiple popovers
. You should differentiate the binding for each row, for example by making a different binding per row:
ForEach(arr) { item in
let binding = Binding<Item?>(
get: { selection == item ? item : nil }, // 👈 returns the item only for the corresponding row
set: { selection = $0 }
)
Text(item.name!)
.id(item.name!)
.onTapGesture {
selection = item
print("selection: \(item.name ?? "")")
}
.popover(item: binding) { item in // 👈 Use the specified binding here
Text(item.addr ?? "")
}
}
Don't forget to make the Item: Equatable
.