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

SwiftUI双击手势搭配NavigationLink跳转DetailView出现随机匹配问题

问题根因
  • 全局状态共用错误:你将跳转控制状态isDoubleTab定义在Home视图的顶层,ForEach循环生成的所有列表项对应的NavigationLink都绑定了这同一个布尔值。任意列表项双击触发状态变为true时,所有列表项的NavigationLink会同时响应跳转,系统最终只会渲染最后一个命中的NavigationLink对应页面,所以出现数据不匹配的随机跳转现象。
  • 代码笔误:示例中存在多处拼写错误会额外导致运行异常,包括:onTapGesture中调用的isDoubleTapped和实际定义的状态名isDoubleTab不一致、NavigationLink参数isActivate应为isActive、视图名VStact/HSTack拼写错误、DetailView中data属性类型声明错误等。
修复方案

推荐使用可选类型存储当前选中的列表项,替代全局布尔跳转状态,避免多个NavigationLink绑定同一状态的冲突问题,以下是兼容iOS14+的修复代码:

import SwiftUI

struct DataArray: Identifiable {
    let id = UUID()
    let number: Int
    let cities: String
    var name1: String?
    var name2: String?
    var name3: String?
    var name4: String?
}

public struct ListDataArray {
    static var dot = [
        DataArray(number: 1,
                  cities: "Baltimore",
                  name1: "John",
                  name2: "Mike"),
        
        DataArray(number: 2,
                  cities: "Frederick"),
        
        DataArray(number: 3,
                  cities: "Catonsville",
                  name1: "Susan",
                  name2: "Oliver",
                  name3: "Jude",
                  name4: "Erik"),
    ]
}

struct Home: View {
    var datas: [DataArray] = ListDataArray.dot
    // 替换布尔状态为可选选中项
    @State var selectedItem: DataArray?

    var body: some View {
        NavigationView {
            LazyVStack(spacing: 10) {
                ForEach(datas) { data in
                    HomeView(data: data)
                        .onTapGesture(count: 2) {
                            // 双击时赋值当前选中项
                            selectedItem = data
                        }
                    Divider()
                        .padding()
                }
            }
            // 全局只放一个NavigationLink绑定可选状态
            .background(
                NavigationLink(
                    destination: selectedItem != nil ? DetailView(data: selectedItem!) : nil,
                    isActive: Binding(
                        get: { selectedItem != nil },
                        set: { if !$0 { selectedItem = nil } }
                    )
                ) {
                    EmptyView()
                }
            )
            .navigationBarHidden(true)
        }
    }
}

struct DetailView: View {
    // 修正属性声明错误
    var data: DataArray
    
    var body: some View {
        // 修正拼写错误
        VStack {
            Text(data.cities)
        }
    }
}

struct HomeView: View {
    var data: DataArray
    var body: some View {
        VStack {
            // 修正拼写错误
            HStack {
                Text(data.cities).padding()
                // 可选值安全处理
                if let name1 = data.name1 {
                    Text(name1)
                }
                if let name2 = data.name2 {
                    Text(name2)
                }
            }
        }
    }
}

如果你的项目最低支持iOS16及以上,可以直接用navigationDestination修饰符实现,代码更简洁:
只需要把Home视图的body修改为:

var body: some View {
    NavigationStack { // 替换NavigationView为NavigationStack
        LazyVStack(spacing: 10) {
            ForEach(datas) { data in
                HomeView(data: data)
                    .onTapGesture(count: 2) {
                        selectedItem = data
                    }
                Divider()
                    .padding()
            }
        }
        .navigationDestination(item: $selectedItem) { item in
            DetailView(data: item)
        }
        .navigationBarHidden(true)
    }
}

内容的提问来源于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 00:48:03