如何为SwiftUI分段Picker动态填充数据?
SwiftUI分段Picker动态数据绑定问题解决
我已实现基于静态列表的SwiftUI Picker功能,但使用动态数据(来自@State变量或环境变量)填充Picker时遇到问题。编写的极简SwiftUI应用创建分段控件后,控件既不显示当前选中项,也不允许用户选择:
import SwiftUI struct ContentView: View { @State private var colors = ["Red", "Green", "Blue"] @State private var selectedColor: Int = 0 var body: some View { VStack { HStack { Spacer().frame(width: 30) Picker("What is your favorite color?", selection: $selectedColor) { ForEach(colors, id: \.self) { aValidColor in Text(aValidColor) } } Spacer().frame(width: 30) } .pickerStyle(.segmented) Spacer().frame(height: 30) Text("Value: \(colors[selectedColor])") } } }
(使用Xcode 15.0 beta 3)
推测问题与ForEach中项的id以及Picker内Text项的tag值有关,但不知如何解决。
编辑:将String数组改为Identifiable结构体数组(每个结构体的id为其在数组中的索引)后功能正常,但这种方式需要维护包含自身数组索引的结构体数组,并不理想。尝试用enumerated()获取对象及其索引,但ForEach的使用方式还没理清。
解决方案
方法1:手动设置Tag绑定数组索引
通过enumerated()获取元素和索引,给每个Picker选项手动设置对应索引的tag,让选中值(Int类型)和索引匹配:
import SwiftUI struct ContentView: View { @State private var colors = ["Red", "Green", "Blue"] @State private var selectedColor: Int = 0 var body: some View { VStack { HStack { Spacer().frame(width: 30) Picker("What is your favorite color?", selection: $selectedColor) { // 将enumerated()序列转为数组,遍历索引和元素 ForEach(Array(colors.enumerated()), id: \.element) { index, color in Text(color) .tag(index) // 绑定索引作为tag } } .pickerStyle(.segmented) Spacer().frame(width: 30) } Spacer().frame(height: 30) Text("Value: \(colors[selectedColor])") } } }
方法2:直接绑定字符串类型选中值
如果数组元素唯一,可以直接将选中值类型设为字符串,tag绑定元素本身,省去索引维护:
import SwiftUI struct ContentView: View { @State private var colors = ["Red", "Green", "Blue"] @State private var selectedColor = "Red" // 选中值为字符串类型 var body: some View { VStack { HStack { Spacer().frame(width: 30) Picker("What is your favorite color?", selection: $selectedColor) { ForEach(colors, id: \.self) { color in Text(color) .tag(color) // tag设为元素本身 } } .pickerStyle(.segmented) Spacer().frame(width: 30) } Spacer().frame(height: 30) Text("Value: \(selectedColor)") } } }
方法3:使用Identifiable自动生成ID
如果偏好使用Identifiable结构,可通过UUID自动生成唯一ID,直接绑定结构体对象,无需手动维护索引:
import SwiftUI struct AColor: Identifiable { let id = UUID() // 自动生成唯一ID let name: String } struct ContentView: View { @State private var colors = [ AColor(name: "Red"), AColor(name:"Green"), AColor(name:"Blue") ] @State private var selectedColor: AColor? // 绑定结构体对象 var body: some View { VStack { HStack { Spacer().frame(width: 30) Picker("What is your favorite color?", selection: $selectedColor) { ForEach(colors) { color in Text(color.name) } } .pickerStyle(.segmented) Spacer().frame(width: 30) } Spacer().frame(height: 30) if let selectedColor = selectedColor { Text("Value: \(selectedColor.name)") } } .onAppear { selectedColor = colors.first // 初始化选中第一个元素 } } }
内容的提问来源于stack exchange,提问作者Duncan C
相关产品推荐
相关产品推荐

