You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI双击手势无法更新选中列表项对应弹出菜单如何解决

核心问题原因

你的代码有三个关键问题导致弹窗永远显示第一个元素:

  1. 全局状态Tapping仅存储了「是否显示弹窗」的布尔值,没有存储当前选中的列表项
  2. 双击手势加在了整个ForEach的外层,无法拿到点击对应位置的具体数据
  3. ContentView中弹出DetailMenu时写死了取数组第0个元素ListDataArray.dot[0]

完整修改方案

1. 调整全局状态类Tapping,新增选中项存储

class Tapping: ObservableObject {
    @Published var isDoubleTab = false
    // 存储当前双击选中的列表项
    @Published var selectedItem: DataArray?
}

2. 修改Home视图,将双击手势绑定到每个单独的列表项

同时修正你代码中的笔误(ForEach遍历对象写错、cities属性不需要可选绑定)

struct Home: View {
    @EnvironmentObject var tap: Tapping
    var datas: [DataArray] = ListDataArray.dot

    var body: some View {
        ScrollView {
            LazyVStack(spacing: 10) {
                ForEach(datas, id: \.id) { data in
                    // 每个列表项单独包容器,绑定对应数据的双击手势
                    VStack(spacing: 4) {
                        if let data1 = data.name1 {
                            Text(data1)
                        }
                        Text(data.cities)
                        if let data2 = data.name2 {
                            Text(data2)
                        }
                    }
                    .onTapGesture(count: 2) {
                        // 存储当前选中项后再打开弹窗
                        tap.selectedItem = data
                        tap.isDoubleTab = true
                    }
                }
            }
        }
    }
}

3. 修正ContentView,动态传入选中的列表项

修正笔误(类名少字母、未注入全局状态)

struct ContentView: View {
    @EnvironmentObject var tap: Tapping
    var body: some View {
        ZStack {
            // 底层始终显示Home页面,不需要切换显示逻辑
            Home()
            // 仅当弹窗开启且选中项不为空时显示菜单
            if tap.isDoubleTab, let selectedItem = tap.selectedItem {
                DetailMenu(dataArr: selectedItem)
                    .background(.ultraThinMaterial)
                    .cornerRadius(12)
            }
        }
    }
}

4. 修正DetailMenu的属性和视图引用错误

修正笔误(属性定义错误、VStack拼写错误、不存在的lyric变量)

struct DetailMenu: View {
    // 正确定义接收的参数类型
    var dataArr: DataArray
    @EnvironmentObject var tap: Tapping
    
    var body: some View {
        VStack(spacing: 20) {
            Text(dataArr.name1 ?? "无对应名称")
            HStack(spacing: 40) {
                Button(action: {
                    tap.isDoubleTab = false
                    // 关闭时清空选中项避免复用异常
                    tap.selectedItem = nil
                }, label: {
                    Image(systemName: "suit.heart")
                        .font(.title)
                })
                
                Button(action: {
                    tap.isDoubleTab = false
                    tap.selectedItem = nil
                }, label: {
                    Image(systemName: "gear")
                        .font(.title)
                })
            }
            .padding()
        }
        .padding(30)
    }
}

5. 补充原有数组定义的语法错误

你原代码中ListDataArray的数组成员初始化少了逗号,补充后即可正常编译:

public struct ListDataArray {
    static var dot = [
        DataArray(number: 1,
            cities: "Baltimore", // 补逗号
            name1: "A",
            name2: "B"),
        DataArray(number: 2,
            cities: "Frederick"),
        DataArray(number: 3,
            cities: "Catonsville", // 补逗号
            name1: "Aa",
            name2: "Bb",
            name3: "Cc",
            name4: "Dd"),
    ]
}

最后别忘了在项目入口注入全局状态

@main
struct YourAppName: App {
    @StateObject private var tap = Tapping()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(tap)
        }
    }
}

内容的提问来源于stack exchange,提问作者Lian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 07:15:05