SwiftUI列表行点击后向模态视图传值异常问题求助
SwiftUI模态视图始终显示首个球员信息的问题解决
问题原因
你在ForEach循环内为每个GridRow绑定了同一个@State变量showingReportCard。当触发状态切换时,所有循环生成的sheet都会被激活,但SwiftUI的视图复用机制会导致最终显示的是循环中第一个sheet的内容,也就是首个球员的信息,尽管控制台能正确打印点击的球员名称。
解决方案
通过绑定选中的球员对象而非布尔状态来解决这个问题,具体步骤如下:
- 让
Players模型遵守Identifiable协议(如果还没实现),确保对象可被唯一识别:
struct Players: Identifiable { let id = UUID() var firstName: String var lastName: String var score: Int }
- 替换状态变量:移除
showingReportCard,改用可选类型的Players变量存储选中的球员:
@State private var selectedPlayer: Players?
- 修改点击事件:点击行时将
selectedPlayer设置为当前球员:
.onTapGesture { selectedPlayer = player print(player.firstName) }
- 使用
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
相关产品推荐
相关产品推荐

