UITextView用UIPickerView作inputView时selectRow方法隔次选中异常
我来帮你梳理下这两个棘手的问题,其实它们的根源都是每次编辑UITextView时都重复创建UIPickerView和inputView容器,导致状态混乱。咱们一步步解决:
问题1:UIPickerView的selectRow每隔一次无法正确选中行
问题原因
你每次在textViewDidBeginEditing里都新建一个全新的UIPickerView和UIView容器,这会导致两个核心问题:
- 新创建的PickerView可能还没完成数据源的初始化(比如系统还没调用
numberOfRowsInComponent),这时候调用selectRow根本不会生效; - 旧的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会导致这个切换出现混乱,从而每隔一次状态栏变成黑色。
解决方案:固定状态栏样式
- 在你的ViewController里重写
preferredStatusBarStyle,固定状态栏样式:
override var preferredStatusBarStyle: UIStatusBarStyle { // 根据你的需求选择,比如.lightContent(浅色文字,适合深色背景)或者.default(深色文字,适合浅色背景) return .lightContent }
- 如果还是有问题,可以在
textViewDidBeginEditing里强制刷新状态栏样式:
func textViewDidBeginEditing(_ textView: UITextView) { print("selectedBankRow: \(selectedRow)") codePicker.selectRow(selectedRow, inComponent: 0, animated: true) textView.inputView = pickerInputView // 强制刷新状态栏样式 setNeedsStatusBarAppearanceUpdate() }
这样修改后,两个问题应该都能解决了——复用PickerView避免了状态混乱,固定状态栏样式解决了变黑的问题。
内容的提问来源于stack exchange,提问作者Anirudha Mahale
相关产品推荐
相关产品推荐

