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

Swift iOS如何将plist数据展示到联动UIPickerView及关联Label

双联动UIPickerView加载plist数据实现方案

核心实现逻辑说明

不需要创建两个独立的UIPickerView实例,直接使用同一个UIPickerView设置2个滚动列(component)即可实现联动:

  • 第1列:展示所有Occupancy Code字段值
  • 第2列:动态展示当前第1列选中编码对应的所有Description of Occupancy值
  • 选中第1列任意项时,自动刷新第2列数据,默认选中第2列首条内容
  • 选择完成后自动匹配关联数据,同步更新两个UILabel的展示内容

具体实现步骤

1. 补全全局属性与控件关联

先在控制器中补充缺失的属性、关联两个展示用Label,替换原有无效的测试数据源:

import UIKit

class ViewController: UIViewController,UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {

    @IBOutlet weak var occupancyTextBox: UITextField!
    // 关联两个展示用Label输出口
    @IBOutlet weak var resultLabel1: UILabel!
    @IBOutlet weak var resultLabel2: UILabel!

    //MARK: Variables
    var toolBar = UIToolbar()
    var pickerViewOccupancy = UIPickerView()
    // plist解析后的全量数据
    var arrData = [[String : String]]()
    // 第一列数据源:所有去重后的Occupancy Code
    var occupancyCodeList = [String]()
    // 分组数据:key为Occupancy Code,value为该编码下对应的所有条目数组
    var codeGroupedData = [String: [[String: String]]]()
    // 记录当前选中的索引
    var selectedCodeIndex = 0
    var selectedDescIndex = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // 解析plist数据
        loadPlistData()
        occupancyTextBox.delegate = self
        createPickerView()
        setupToolBar()
        // 默认选中第一组第一条数据,初始化Label展示
        updateRelatedDisplay()
    }
}

2. 修正plist数据解析与分组逻辑

原有解析逻辑只存储了两个字段,需要把plist全量字段读取后按Occupancy Code分组,供联动使用:

extension ViewController {
    func loadPlistData() {
        guard let url = Bundle.main.url(forResource: "firedata", withExtension: "plist"),
              let data = try? Data(contentsOf: url),
              let plist = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [[String : Any]] else {
            return
        }
        // 清空旧数据
        arrData.removeAll()
        occupancyCodeList.removeAll()
        codeGroupedData.removeAll()
        
        for item in plist {
            // 读取plist中所有需要的字段,字段名和实际plist保持一致即可
            var dict = [String: String]()
            dict["Occupancy Code"] = item["Occupancy Code"] as? String ?? ""
            dict["Description of Occupancy"] = item["Description of Occupancy"] as? String ?? ""
            // 补充第三项关联字段、绑定到编码的关联字段,替换为你自己plist里的实际字段名
            dict["ThirdRelatedValue"] = item["ThirdRelatedValue"] as? String ?? ""
            dict["CodeBindValue"] = item["CodeBindValue"] as? String ?? ""
            
            arrData.append(dict)
            
            // 按Occupancy Code分组
            let code = dict["Occupancy Code"]!
            if codeGroupedData[code] == nil {
                codeGroupedData[code] = [[String: String]]()
                occupancyCodeList.append(code)
            }
            codeGroupedData[code]?.append(dict)
        }
    }
}

3. 配置PickerView与工具栏

原有工具栏没有添加操作按钮,这里补全完成按钮逻辑,同时绑定PickerView作为输入框的输入视图:

extension ViewController {
    func createPickerView() {
        pickerViewOccupancy.delegate = self
        pickerViewOccupancy.dataSource = self
        occupancyTextBox.inputView = pickerViewOccupancy
    }
    
    func setupToolBar() {
        toolBar.sizeToFit()
        let doneBtn = UIBarButtonItem(title: "完成", style: .done, target: self, action: #selector(donePickerSelect))
        let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        toolBar.items = [flexSpace, doneBtn]
        toolBar.isUserInteractionEnabled = true
        occupancyTextBox.inputAccessoryView = toolBar
    }
    
    @objc func donePickerSelect() {
        // 收起选择器
        view.endEditing(true)
        // 更新输入框文本
        let currentCode = occupancyCodeList[selectedCodeIndex]
        occupancyTextBox.text = "Occupancy: \(currentCode)"
        // 更新关联Label展示
        updateRelatedDisplay()
    }
    
    // 抽离Label更新逻辑,选中项变化时统一调用
    func updateRelatedDisplay() {
        guard occupancyCodeList.count > selectedCodeIndex,
              let descList = codeGroupedData[occupancyCodeList[selectedCodeIndex]],
              descList.count > selectedDescIndex else {
            return
        }
        let currentItem = descList[selectedDescIndex]
        // 第一个Label展示两个选中值对应的第三项关联数据
        resultLabel1.text = currentItem["ThirdRelatedValue"]
        // 第二个Label展示第一个选中项绑定的关联数据
        resultLabel2.text = currentItem["CodeBindValue"]
    }
}

4. 实现PickerView代理与数据源的联动逻辑

替换原有单轮的代理实现,完成双列联动逻辑:

//MARK: PickerView Methods
extension ViewController {
    // 返回2列,对应编码、描述两个选择项
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if component == 0 {
            // 第一列返回编码总数
            return occupancyCodeList.count
        } else {
            // 第二列返回当前选中编码对应的描述总数
            let currentCode = occupancyCodeList[selectedCodeIndex]
            return codeGroupedData[currentCode]?.count ?? 0
        }
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if component == 0 {
            return occupancyCodeList[row]
        } else {
            let currentCode = occupancyCodeList[selectedCodeIndex]
            return codeGroupedData[currentCode]?[row]["Description of Occupancy"]
        }
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if component == 0 {
            // 选中第一列编码时,重置描述选中索引为0,刷新第二列
            selectedCodeIndex = row
            selectedDescIndex = 0
            pickerView.reloadComponent(1)
            pickerView.selectRow(0, inComponent: 1, animated: true)
        } else {
            // 选中第二列描述时,记录索引
            selectedDescIndex = row
        }
        // 实时更新展示内容
        updateRelatedDisplay()
    }
}

注意事项

  • 代码中ThirdRelatedValue、CodeBindValue两个字段名需要和你自己plist中实际存储的字段名保持一致,直接替换即可
  • 如果你的plist中同一个Occupancy Code只对应一条Description,直接在分组后取首项即可,第二列可以设置为只展示1行不可滚动,基础逻辑不需要改动
  • 如果需要自定义PickerView每行的样式(比如调整字体、颜色),可以替换titleForRow代理为viewForRow代理实现自定义视图

内容的提问来源于stack exchange,提问作者Uvesh Imam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 14:06:23