自定义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
相关产品推荐
相关产品推荐

