SwiftUI结合SwiftData实现动态联动Picker问题求助
问题分析与解决方案
核心问题
PickerParadasView中Query使用错误:尝试在初始化方法中绑定@Binding var paradas并赋值Query实例,不符合 SwiftData@Query属性包装器的使用规范。- 过滤条件硬编码:Parada 的过滤条件固定为
"2",无法根据选中的 Ruta 动态更新。 idRutaNuevo赋值逻辑错误:选中 Ruta 后,idRutaNuevo被设置为相反值(选中"1"时设为"2"),导致过滤逻辑完全颠倒。- 未处理选中状态空值:第一个 Picker 的默认选项未设置
tag(nil),可能导致选中状态异常。
修正后的完整代码
import SwiftUI import SwiftData struct FormFavouritesTestView: View { @State var loadData: ReadDataModel? @State var idRutaNuevo: String = "1" @Environment(\.modelContext) private var modelContext @State private var selectedParada: Parada? @Query(sort: \Ruta.idRuta) private var rutas: [Ruta] @State private var selectedRuta: Ruta? private func cargar() { loadData = ReadDataModel(modelContext: modelContext) } var body: some View { NavigationView { Form { Section(header: Text("Dirección y parada")) { // 第一个选择器:选择Ruta Picker(selection: $selectedRuta, label: Text("Dirección")) { Text("Selecciona") .tag(nil as Ruta?) // 添加空标签匹配初始nil状态 ForEach(rutas) { ruta in Text("\(ruta.idRuta) - \(ruta.name)") .tag(Optional(ruta)) } } .onChange(of: selectedRuta) { newValue in guard let ruta = newValue else { return } // 修正:直接将选中的Ruta id赋值给idRutaNuevo idRutaNuevo = ruta.idRuta print("选中的Ruta ID: \(idRutaNuevo)") } // 第二个选择器:根据选中的Ruta过滤Parada PickerParadasView(selectedParada: $selectedParada, idRutaNuevo: $idRutaNuevo) Button("Done") { print("选中的Dirección: \(idRutaNuevo)") if let parada = selectedParada { print("选中的Parada: \(parada.id) - \(parada.title)") } } } } .navigationTitle("Nueva Ruta") } .onAppear { cargar() // 初始化选中第一个Ruta selectedRuta = rutas.first if let ruta = selectedRuta { idRutaNuevo = ruta.idRuta print("初始Ruta ID: \(idRutaNuevo)") } } } } struct PickerParadasView: View { @Binding var selectedParada: Parada? @Binding var idRutaNuevo: String // 使用SwiftData Query动态获取过滤后的Parada @Query private var paradas: [Parada] init(selectedParada: Binding<Parada?>, idRutaNuevo: Binding<String>) { self._selectedParada = selectedParada self._idRutaNuevo = idRutaNuevo // 初始化查询:根据初始idRutaNuevo过滤并按id排序 let initialPredicate = #Predicate<Parada> { $0.idRuta == idRutaNuevo.wrappedValue } self._paradas = Query(filter: initialPredicate, sort: \.id) } var body: some View { Picker(selection: $selectedParada, label: Text("Parada")) { ForEach(paradas) { parada in Text("\(parada.id) - \(parada.title)") .tag(Optional(parada)) } } // 当idRutaNuevo变化时,更新查询条件 .onChange(of: idRutaNuevo) { newId in let newPredicate = #Predicate<Parada> { $0.idRuta == newId } self._paradas = Query(filter: newPredicate, sort: \.id) // 清空选中的Parada,避免选中已不存在的选项 selectedParada = nil } } } #Preview { FormFavouritesTestView() .modelContainer(for: [Parada.self, Ruta.self, Favorito.self], inMemory: true) }
关键修改说明
- 修正
Query使用方式:在PickerParadasView中正确使用@Query属性包装器,通过初始化和onChange动态更新查询条件。 - 动态过滤逻辑:当
idRutaNuevo变化时,重新创建Query实例,自动从 SwiftData 获取匹配的 Parada 数据。 - 修复
idRutaNuevo赋值:直接将选中的 Ruta id 赋值给idRutaNuevo,确保过滤条件与选中的 Ruta 一致。 - 空值处理:为第一个 Picker 的默认选项添加
tag(nil),并在 Parada 列表更新时清空选中状态,避免无效选择。 - 冗余代码移除:删除不必要的
queryRutas查询,统一使用排序后的rutas数据源。
内容的提问来源于stack exchange,提问作者Ricardo A.
相关产品推荐
相关产品推荐

