首页 > 解决方案 > 将 .popover 附加到列表中的 ForEach 或部分会创建多个弹出框

问题描述

我有List多个Section,每个部分都有不同类型的数据。对于每个部分,我想单击一个项目以显示一个弹出框。

问题是,如果我将 附加.popoverSectionorForEach然后.popover似乎将应用于列表中的每个条目。因此,即使仅单击一个项目,也会为每个项目创建弹出框。

示例代码如下。我无法将其附加.popover到,List因为在我的情况下,有 2 种不同的样式,.popover并且每个视图只能.popover附加一个。

struct Item: Identifiable {
    var id = UUID()
    var title: String
}

var items: [Item] = [
    Item(title: "Item 1"),
    Item(title: "Item 2"),
    Item(title: "Item 3"),
]

struct PopoverView: View {
    @State var item: Item
    
    var body: some View {
        print("new PopoverView")
        return Text("View for \(item.title)")
    }
}

struct ContentView: View {
    @State var currentItem: Item?
    
    var body: some View {
        List {
            Section(header: Text("Items")) {
                ForEach(items) { item in
                    Button(action: { currentItem = item }) {
                        Text("\(item.title)")
                    }
                }
            }
        }
    }
}

我想出的当前最佳解决方案是将弹出框附加到每个弹出框Button,然后仅允许一个基于弹出框的弹出框currentItem

                    Button(action: { currentItem = item }) {
                        Text("\(item.title)")
                    }
                    .popover(isPresented: .init(get: { currentItem == item },
                                                set: { $0 ? (currentItem = item) : (currentItem = nil) })) {
                        PopoverView(item: item)
                    }

有没有更好的方法来做到这一点?

解决这个问题的加分点:当我使用我的 hack 时,向下拖动的动作似乎出现了故障,并且视图再次从顶部出现。不知道这是怎么回事。

标签: iosswiftui

解决方案


您始终可以为您的项目创建单独的视图。

struct MyGreatItemView: View {
    @State var isPresented = false
    var item: Item
   
    var body: some View {

          Button(action: { isPresented = true }) {
                        Text("\(item.title)")
                    }
           .popover(isPresented: $isPresented) {
                        PopoverView(item: item)
                    }

    }
}

并将其实现到 ContentView:

struct ContentView: View {  
    var body: some View {
        List {
            Section(header: Text("Items")) {
                ForEach(items) { item in
                   MyGreatItemView(item: item)
                }
            }
        }
    }
}

推荐阅读