SwiftUI中使用结构体作为Picker元素时如何保存切换后的值?
问题解决思路
核心问题是你当前修改的是selectedPlayer这个副本,而非playerList数组里的原始玩家实例,切换Picker后自然丢失数据。以下是具体修复步骤:
关键修改点
- 将
playerList声明为@State变量,让SwiftUI能跟踪数组内元素的变化 - Picker绑定数组索引而非直接绑定Players实例,确保修改的是数组里的原始数据
- 移除冗余的
hours状态变量,直接绑定到选中玩家的hourString
修改后的完整代码
import SwiftUI struct Players: Hashable { var playerNumber: String var killString: String var kills: Double var hourString: String var hours: Double } struct ContentView: View { // 改为@State变量,允许修改数组内的元素 @State private var playerList: [Players] = [ Players(playerNumber: "Player 1", killString: "", kills: 0, hourString: "", hours: 0), Players(playerNumber: "Player 2", killString: "", kills: 0, hourString: "", hours: 0), Players(playerNumber: "Player 3", killString: "", kills: 0, hourString: "", hours: 0), Players(playerNumber: "Player 4", killString: "", kills: 0, hourString: "", hours: 0), Players(playerNumber: "Player 5", killString: "", kills: 0, hourString: "", hours: 0), ] // 绑定数组索引,而非直接绑定Players实例 @State private var selectedPlayerIndex = 0 var body: some View { NavigationView { VStack(spacing: 30){ Group{ Text(playerList[selectedPlayerIndex].playerNumber) .font(.system(size: 50)) }.frame(width:350, height: 100) .background(Color("AppSwag")).cornerRadius(30) .foregroundColor(.white) Text("Select a Player") .padding(10) Picker("Select Player", selection: $selectedPlayerIndex){ ForEach(playerList.indices, id: \.self) { index in Text(playerList[index].playerNumber) } }.pickerStyle(.segmented) HStack{ Text("Enter Players Hours:") // 直接绑定到选中玩家的hourString,无需中间变量 TextField("", text: $playerList[selectedPlayerIndex].hourString) .frame(width: 150, height: 50) .background(Color.gray.opacity(0.5)) .cornerRadius(10) } HStack{ Text("Enter Players Kills:") TextField("", text: $playerList[selectedPlayerIndex].killString) .frame(width: 150, height: 50) .background(Color.gray.opacity(0.5)) .cornerRadius(10) } Text("\(playerList[selectedPlayerIndex].playerNumber)'s values: \(playerList[selectedPlayerIndex].hourString) ") }// Vstack .navigationTitle("CSGO Calculator") .padding() } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
额外说明
- 因为结构体是值类型,直接修改
selectedPlayer只会修改副本,而通过索引操作playerList里的元素,才会真正修改数据源 - 移除
onSubmit是因为直接绑定TextField到数据源,输入时会实时更新,无需手动提交(如果需要提交后再更新,可以保留onSubmit,但要更新数组对应元素)
内容的提问来源于stack exchange,提问作者IMissSometimes
相关产品推荐
相关产品推荐

