You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:44:51