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

自定义UIPickerView绑定UITextField后无数据显示的问题排查

自定义UIPickerView绑定UITextField后无数据显示的问题排查

嗨,我帮你分析下代码里的问题,其实核心原因很明确,还有几个小细节可以优化,让你的PickerView正常显示数据:

1. 最关键的问题:PickerView的代理和数据源未赋值

你创建了myPickerView,但没有告诉它谁来提供数据(dataSource)和谁来处理交互逻辑(delegate)。在你的init方法里,需要添加两行代码给PickerView绑定代理和数据源:

init(ufExpedicaoTextField: UITextField) {
    self.myTextField = ufExpedicaoTextField
    myPickerView = UIPickerView()
    // 添加这两行!
    myPickerView.delegate = self
    myPickerView.dataSource = self
    myTextField.inputView = myPickerView
    super.init(nibName: nil, bundle: nil)
}

没有这两行的话,PickerView不知道要从哪里获取行数、标题这些数据,自然就显示为空了。

2. 更合理的封装方式:用UIView子类替代UIViewController

你现在把PickerView封装成了UIViewController,但实际上inputView本质是一个视图,用ViewController来封装会带来不必要的生命周期管理问题,而且结构也不太合理。更推荐改成UIView子类,代码会更清晰,也更符合iOS的视图设计逻辑:

class EstadosPickerView: UIView, UIPickerViewDelegate, UIPickerViewDataSource {
    // 把数据放在内部,封装性更好
    private let estadosArray = ["AC","AL","AP","AM","BA","CE","ES","GO","MA","MT","MS","MG","PA","PB","PR","PE","PI","RJ","RN","RS","RO","RR","SC","SP","SE","TO","DF"]
    // 用weak避免循环引用
    private weak var targetTextField: UITextField?
    private let pickerView = UIPickerView()

    init(textField: UITextField) {
        self.targetTextField = textField
        super.init(frame: .zero)
        setupPicker()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupPicker() {
        // 绑定代理和数据源
        pickerView.delegate = self
        pickerView.dataSource = self
        // 设置为textField的输入视图
        targetTextField?.inputView = pickerView

        // 额外添加一个工具栏,方便用户收起Picker(体验更友好)
        let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
        let doneBtn = UIBarButtonItem(title: "完成", style: .done, target: self, action: #selector(hidePicker))
        toolbar.items = [UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil), doneBtn]
        targetTextField?.inputAccessoryView = toolbar
    }

    @objc private func hidePicker() {
        targetTextField?.resignFirstResponder()
    }

    // MARK: - UIPickerView 协议方法
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return estadosArray.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return estadosArray[row]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        targetTextField?.text = estadosArray[row]
    }
}

3. 使用方式(在你的UIViewController里)

这样初始化和绑定就很简单了:

// 假设你已经创建了ufExpedicaoTextField并添加到视图
let ufPicker = EstadosPickerView(textField: ufExpedicaoTextField)

这样修改后,你的PickerView应该就能正常显示所有州的缩写了,而且交互体验也更好~

备注:内容来源于stack exchange,提问作者fabiobh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 15:03:11