SwiftUI中跨结构体传值实现Picker双向同步所需变量类型
SwiftUI 双Picker双向选中同步实现方案
要实现两个独立View结构体之间的双向选中同步,你需要使用 @Binding 类型变量,配合父视图持有的@State作为单一可信数据源即可实现需求。
现有代码问题
你当前的实现无法同步的核心原因:两个Picker组件各自通过@State在内部维护了独立的选中状态,两份状态完全隔离,任意一个选择器的值变更都不会通知到另一个选择器,自然无法同步。
实现步骤
- 将两个Picker组件内部原来存储选中值的
@State变量替换为@Binding类型,移除变量的默认初始值。子组件不需要自己持有状态,只需要对外暴露可读写的绑定接口即可。 - 在承载两个Picker的父页面中,定义一个统一的
@State变量作为唯一的选中值存储源。 - 父页面调用两个Picker时,把这个
@State变量的绑定(变量名前加$前缀)分别传入两个组件的@Binding参数。此时两个组件操作的是同一份状态数据,任意一边修改选中值,两个组件都会自动同步刷新。
修改后的代码示例
调整后的两个Picker组件
struct CurrentSystemPicker: View { // 选项数据保持不变 let currentSystems: [String] = ["Air Conditioning", "Furnace", "Furance Air Conditioning", "Heat Pump"] // 替换原有@State为@Binding,移除默认值 @Binding var selectedSystem: String var body: some View { Menu { Picker("picker", selection: $selectedSystem) { ForEach(currentSystems, id: \.self) { system in Text(system).tag(system) } } .labelsHidden() .pickerStyle(InlinePickerStyle()) } label: { HStack { Rectangle() .foregroundColor(Color(.systemBackground)) } .fixedSize() .frame(width: ESConstants().IS_IPAD ? 275 : 110, height: ESConstants().IS_IPAD ? 75 : 50) .padding(.horizontal) .background(Color.white) .cornerRadius(ESConstants().IS_IPAD ? 15 : 10) .overlay( RoundedRectangle(cornerRadius: ESConstants().IS_IPAD ? 15 : 10) .stroke(Color.eSaverGray, lineWidth: 1) ) .overlay(Text(selectedSystem)) .foregroundColor(Color.black) } } } struct UserSystemPicker: View { // 选项数据保持不变 let userSystems: [String] = ["Air Conditioning", "Furnace", "Furance Air Conditioning", "Heat Pump"] // 替换原有@State为@Binding,移除默认值 @Binding var selectedSystem: String var body: some View { Menu { Picker("picker", selection: $selectedSystem) { ForEach(userSystems, id: \.self) { system in Text(system).tag(system) } } .labelsHidden() .pickerStyle(InlinePickerStyle()) } label: { HStack { Rectangle() .foregroundColor(Color(.systemBackground)) } .fixedSize() .frame(width: ESConstants().IS_IPAD ? 275 : 110, height: ESConstants().IS_IPAD ? 75 : 50) .padding(.horizontal) .background(Color.white) .cornerRadius(ESConstants().IS_IPAD ? 15 : 10) .overlay( RoundedRectangle(cornerRadius: ESConstants().IS_IPAD ? 15 : 10) .stroke(Color.eSaverGray, lineWidth: 1) ) .overlay(Text(selectedSystem)) .foregroundColor(Color.black) } } }
父页面调用示例
struct ContainerPage: View { // 唯一的状态源,存储共享的选中值,可按需设置初始值 @State private var sharedSelectedSystem: String = "Heat Pump" var body: some View { VStack(spacing: 20) { // 传入同一个绑定值给两个选择器 CurrentSystemPicker(selectedSystem: $sharedSelectedSystem) UserSystemPicker(selectedSystem: $sharedSelectedSystem) } } }
小提示:如果你需要保留原来两个选择器不同的占位显示逻辑(比如未选择时分别显示"Current System"、"Future system"),可以给
sharedSelectedSystem设置对应的空状态初始值,或者在label的Text显示逻辑中加判断即可,核心是不要在子组件内部单独维护选中状态。
内容的提问来源于stack exchange,提问作者KingGizzard237
相关产品推荐
相关产品推荐

