I have been making a little test app to try and learn Swift 3 / iOS better. I started a while ago with with Swift 2 but stopped, so getting back into it, but there is so much iOS to learn!

It seems to work fine, and I made it so that it worked by inserting the pickerview value into the textfield when a user presses the "done" button. I found that without doing that if a user wants the first value of the pickerview it doesn't get inserted like it does when you scroll to another value. I left in the relative code for my controller.

class ViewController: UITableViewController, UIPickerViewDataSource, UIPickerViewDelegate {
 let pickerData: [String] = ["1", "2", "3", "4"]
 var picker = UIPickerView()

 @IBOutlet weak var textField: UITextField!

 // set the pickerview for number of periods
func setPickerView(){
    picker.dataSource = self
    picker.delegate = self
    textField.inputView = picker
    textField.inputAccessoryView = initToolBar()

// build the toolbar for uipicker, so a user can select a value
func initToolBar() -> UIToolbar {
    let toolBar = UIToolbar()
    toolBar.barStyle = UIBarStyle.default
    toolBar.isTranslucent = true
    toolBar.tintColor = UIColor(red:14.0/255, green:122.0/255, blue:254.0/255, alpha: 1)
    // TODO need to update actions for all buttons
    let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: nil)
    let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(pickerDoneAction))
    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
    toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
    toolBar.isUserInteractionEnabled = true

    return toolBar

// Take pickerview value and insert into textfield, this stops the first row on load not being loaded into textfield
func pickerDoneAction(sender: UITextField){
    let indexPath = picker.selectedRow(inComponent: 0)
    textField.text = pickerData[indexPath]
    // resign first responder dropping the uipicker
    UIApplication.shared.sendAction(#selector(resignFirstResponder), to:nil, from:nil, for:nil)

// Pickerview delegates
func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 }
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {return pickerData.count}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {return pickerData[row]}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    textField.text = pickerData[row]

I'd like to take this if the code is pretty decent and make it work for multiple uipickers with different data sources on the same screen. Although I'm not too sure of how yet


A simple fix would be adding an empty extra value at the beginning of the data source

let pickerData: [String] = ["","1", "2", "3", "4"]

or you could let textField.text = pickerData[0] as soon as they start editing the textField


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.