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

UITextView用UIPickerView作inputView时selectRow方法隔次选中异常

我来帮你梳理下这两个棘手的问题,其实它们的根源都是每次编辑UITextView时都重复创建UIPickerView和inputView容器,导致状态混乱。咱们一步步解决:


问题1:UIPickerView的selectRow每隔一次无法正确选中行

问题原因

你每次在textViewDidBeginEditing里都新建一个全新的UIPickerView和UIView容器,这会导致两个核心问题:

  1. 新创建的PickerView可能还没完成数据源的初始化(比如系统还没调用numberOfRowsInComponent),这时候调用selectRow根本不会生效;
  2. 旧的PickerView实例可能还残留着之前的选中状态,和新实例的状态冲突,看起来就像是选中了上上次的选项——虽然你打印的selectedRow值是对的,但新Picker还没跟上这个状态。

解决方案:复用PickerView实例

把PickerView和inputView改成ViewController的类属性,只初始化一次,每次编辑时直接复用这个实例,状态就会和你的selectedRow保持同步。

修改后的代码示例:

class YourViewController: UIViewController, UITextViewDelegate, UIPickerViewDataSource, UIPickerViewDelegate {
    // 把picker和inputView改成类属性,只初始化一次
    private var codePicker: UIPickerView!
    private var pickerInputView: UIView!
    var selectedRow = 0 // 假设这是你保存选中行的变量
    @IBOutlet weak var yourTextView: UITextView! // 你的UITextView
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 初始化picker和inputView
        setupPickerInputView()
        // 设置textView的代理
        yourTextView.delegate = self
    }
    
    private func setupPickerInputView() {
        pickerInputView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 240))
        codePicker = UIPickerView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 240))
        codePicker.tag = 2
        codePicker.dataSource = self
        codePicker.delegate = self
        codePicker.showsSelectionIndicator = true
        pickerInputView.addSubview(codePicker)
    }
    
    func textViewDidBeginEditing(_ textView: UITextView) {
        print("selectedBankRow: \(selectedRow)")
        // 直接复用已有的picker,设置选中行
        codePicker.selectRow(selectedRow, inComponent: 0, animated: true)
        // 给textView赋值inputView
        textView.inputView = pickerInputView
    }
    
    // 别忘了实现PickerView的数据源和代理方法
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1 // 你的Picker只有一个组件
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        // 返回你的数据源行数,比如银行列表的数量
        return yourBankList.count // 替换成你的数据源数组
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        // 返回每行的标题
        return yourBankList[row] // 替换成你的数据源数组
    }
    
    // 用户选中Picker行时,更新selectedRow并关闭编辑
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        selectedRow = row
        yourTextView.text = yourBankList[row] // 更新textView内容
        yourTextView.resignFirstResponder() // 退出编辑状态
    }
}

问题2:状态栏每隔一次变黑

问题原因

每次创建新的inputView时,系统可能会触发状态栏样式的切换逻辑,重复创建inputView会导致这个切换出现混乱,从而每隔一次状态栏变成黑色。

解决方案:固定状态栏样式

  1. 在你的ViewController里重写preferredStatusBarStyle,固定状态栏样式:
override var preferredStatusBarStyle: UIStatusBarStyle {
    // 根据你的需求选择,比如.lightContent(浅色文字,适合深色背景)或者.default(深色文字,适合浅色背景)
    return .lightContent
}
  1. 如果还是有问题,可以在textViewDidBeginEditing里强制刷新状态栏样式:
func textViewDidBeginEditing(_ textView: UITextView) {
    print("selectedBankRow: \(selectedRow)")
    codePicker.selectRow(selectedRow, inComponent: 0, animated: true)
    textView.inputView = pickerInputView
    // 强制刷新状态栏样式
    setNeedsStatusBarAppearanceUpdate()
}

这样修改后,两个问题应该都能解决了——复用PickerView避免了状态混乱,固定状态栏样式解决了变黑的问题。

内容的提问来源于stack exchange,提问作者Anirudha Mahale

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:01:40