Search code examples
iosswiftuitextfielduipickerview

UIPickerView Behaving Erratically


So I feel stupid asking about this, but I simply cannot figure out what is going wrong. Basically, when I click a textField that has a UIPickerView as its inputView it will show up very quickly and then disappear. However, the toolBar (its accessoryView still remains on screen). I haven't seen anyone else online who has experienced this, so that's why I had to ask it on SO.

At first I thought it had something do with when I was setting the pickerView's .isHidden property. But I omitted those calls to no effect.

Thus, I will be including all of the code related to my pickerViews since I really don't know where the issue is. I'm sure it's something minor I'm missing, but any help would be appreciated.

class myAssessmentsViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {

@IBOutlet weak var contentSelectionTextField: UITextField!
@IBOutlet weak var contentOrderingTextField: UITextField!

var contentSelectionPickerView: UIPickerView = UIPickerView()
var contentOrderingPickerView: UIPickerView = UIPickerView()

var contentSelectionOptions: [String] = ["All", "Physics HL", "Chemistry HL", "Spanish Ab SL"]
var contentOrderingOptions: [String] = ["Date", "Subject", "Grade", "Title"]

required init?(coder aDecoder: NSCoder) {

    super.init(coder: aDecoder)

}

override func viewDidLoad() {
    super.viewDidLoad()

    contentSelectionPickerView.tag = 1 //for the delegate methods
    contentSelectionPickerView.isHidden = true //commenting this out did nothing
    contentSelectionPickerView.delegate = self
    contentSelectionPickerView.dataSource = self

    contentSelectionTextField.inputView = contentSelectionPickerView //set pickerView as responder
    contentSelectionTextField.delegate = self

    contentOrderingPickerView.tag = 2 //for the delegate methods
    contentOrderingPickerView.isHidden = true //commenting this out also did nothing
    contentOrderingPickerView.delegate = self
    contentOrderingPickerView.dataSource = self

    initializePickerViewToolBar(clearButtonFunc: "clearPressedContentSelectionPickerView", doneButtonFunc: "donePressedContentSelectionPickerView", textField: contentSelectionTextField)
    initializePickerViewToolBar(clearButtonFunc: "clearPressedContentOrderingPickerView", doneButtonFunc: "donePressedContentOrderingPickerView", textField: contentOrderingTextField)

    contentOrderingTextField.inputView = contentOrderingPickerView //set pickerView as responder
    contentOrderingTextField.delegate = self


    // Do any additional setup after loading the view.
}

func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1 //same for both pickers
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

    if pickerView.tag == 1 { //contentSelectionPickerView
        return contentSelectionOptions.count
    } else if pickerView.tag == 2 { //contentOrderingPickerView
        return contentOrderingOptions.count
    } else {
        return 1
    }

}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

    self.view.endEditing(true)

    if pickerView.tag == 1 { //contentSelectionPickerView
        return contentSelectionOptions[row]
    } else if pickerView.tag == 2 { //contentOrderingPickerView
        return contentOrderingOptions[row]
    } else {
        return "1"
    }

}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

    if pickerView.tag == 1 {
        contentSelectionTextField.text = contentSelectionOptions[row]
    } else if pickerView.tag == 2 {
        contentOrderingTextField.text = contentOrderingOptions[row]
    }

}

func textFieldDidBeginEditing(_ textField: UITextField) {

    if textField == contentSelectionTextField {
        contentSelectionPickerView.isHidden = false //also was not source of problem
    } else if textField == contentOrderingTextField {
        contentOrderingPickerView.isHidden = false //same here
    }

}

func donePressedContentSelectionPickerView(){
    contentSelectionTextField.resignFirstResponder()
}
func donePressedContentOrderingPickerView(){
    contentOrderingTextField.resignFirstResponder()
}

func clearPressedContentSelectionPickerView(){
    contentSelectionTextField.resignFirstResponder()
    contentSelectionTextField.text = ""
}
func clearPressedContentOrderingPickerView(){
    contentOrderingTextField.resignFirstResponder()
    contentOrderingTextField.text = ""
}

func initializePickerViewToolBar(clearButtonFunc: String, doneButtonFunc: String, textField: UITextField){

    let toolBar = UIToolbar(frame: CGRect(x: 0, y: textField.frame.size.height/6, width:  textField.frame.size.width, height: 40.0))
    toolBar.layer.position = CGPoint(x: textField.frame.size.width/2, y: textField.frame.size.height-20.0)
    toolBar.barStyle = .default
    toolBar.tintColor = UIColor.black

    let clearButton = UIBarButtonItem(title: "Clear", style: .plain, target: self, action: Selector(clearButtonFunc))
    let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: Selector(doneButtonFunc))
    let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)

    toolBar.setItems([clearButton,flexSpace,doneButton], animated: true)
    toolBar.isUserInteractionEnabled = true

    textField.inputAccessoryView = toolBar

}

}

Here is also a photo of what I am talking about visually. As you can see at the bottom of the screen the accessoryView is still visible but the content isn't. I would think that the accessoryView would be a subview of the UIPickerView and that they would disappear together but that is apparently not the case.

The issue

Again, apologies for all of the code (and the large image), I know it is a lot to read through, but any insight would be greatly appreciated!


Solution

  • So it turns out that one of the answers from SO that I was following told me to include self.view.endEditing(true) in my pickerViewTitleForRow delegate method. This meant whenever the titles were being set, the first responder was being dismissed, causing this issue. Removing it caused the problem to disappear. Thanks to @MikeTaverne for pointing it out.