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

SwiftUI列表行点击后向模态视图传值异常问题求助

SwiftUI模态视图始终显示首个球员信息的问题解决

问题原因

你在ForEach循环内为每个GridRow绑定了同一个@State变量showingReportCard。当触发状态切换时,所有循环生成的sheet都会被激活,但SwiftUI的视图复用机制会导致最终显示的是循环中第一个sheet的内容,也就是首个球员的信息,尽管控制台能正确打印点击的球员名称。

解决方案

通过绑定选中的球员对象而非布尔状态来解决这个问题,具体步骤如下:

  1. 让Players模型遵守Identifiable协议(如果还没实现),确保对象可被唯一识别:
struct Players: Identifiable {
    let id = UUID()
    var firstName: String
    var lastName: String
    var score: Int
}
  1. 替换状态变量:移除showingReportCard,改用可选类型的Players变量存储选中的球员:
@State private var selectedPlayer: Players?
  1. 修改点击事件:点击行时将selectedPlayer设置为当前球员:
.onTapGesture {
    selectedPlayer = player
    print(player.firstName)
}
  1. 使用sheet(item:)替代sheet(isPresented:):该方法会根据绑定的可选对象是否存在来显示模态视图,自动关联对应的球员信息:
.sheet(item: $selectedPlayer) { selected in
    TutoringView(firstName: selected.firstName)
}

完整修改后的代码

import SwiftUI

struct Players: Identifiable {
    let id = UUID()
    var firstName: String
    var lastName: String
    var score: Int
}

struct PlayerView: View {
    let players = [
        Players(firstName: "Roy", lastName: "Kent",score:100),
        Players(firstName: "Richard", lastName: "Montlaur",score:100),
        Players(firstName: "Dani", lastName: "Rojas",score:100)
    ]
    @State private var selectedPlayer: Players?

    var body: some View {
        NavigationStack {
            List{
                Grid{
                    GridRow {
                        Text("First Name")
                        Text("Last Name")
                        Text("Score")
                    }
                    Divider()
                    ForEach(players){ player in
                        GridRow {
                            Text(player.firstName)
                            Text(player.lastName)
                            Text("\(player.score)")
                        }
                        .onTapGesture {
                            selectedPlayer = player
                            print(player.firstName)
                        }
                        .sheet(item: $selectedPlayer) { selected in
                            TutoringView(firstName: selected.firstName)
                        }
                    }
                }
            }
        }
    }
}

// 示例TutoringView实现
struct TutoringView: View {
    let firstName: String
    var body: some View {
        Text("球员姓名:\(firstName)")
            .navigationTitle("球员详情")
    }
}

原理说明

sheet(item:)会直接与选中的球员对象绑定,每次点击不同行时,selectedPlayer会更新为对应的球员实例,模态视图因此能正确显示当前点击球员的信息,避免了视图复用带来的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 19:10:19