UIPickerView
iOS Development
Swift Programming
Mobile App Development
iOS UI Elements

How To Get Selected Value From UIPickerView

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

UIPickerView is a UIKit component that presents a spinning-wheel interface for selecting from a set of options. To get the selected value, you call selectedRow(inComponent:) on the picker view and use that index to look up the value in your data source array. The picker view uses a delegate/data source pattern — you provide the data through UIPickerViewDataSource and respond to selections through UIPickerViewDelegate. There is no .selectedValue property; you must map the selected row index back to your data model.

Basic Setup

swift
1import UIKit
2
3class PickerViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
4
5    let pickerView = UIPickerView()
6    let fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry"]
7
8    override func viewDidLoad() {
9        super.viewDidLoad()
10
11        pickerView.delegate = self
12        pickerView.dataSource = self
13        pickerView.translatesAutoresizingMaskIntoConstraints = false
14        view.addSubview(pickerView)
15
16        NSLayoutConstraint.activate([
17            pickerView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
18            pickerView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
19        ])
20    }
21
22    // MARK: - UIPickerViewDataSource
23
24    func numberOfComponents(in pickerView: UIPickerView) -> Int {
25        return 1
26    }
27
28    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
29        return fruits.count
30    }
31
32    // MARK: - UIPickerViewDelegate
33
34    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
35        return fruits[row]
36    }
37
38    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
39        let selectedFruit = fruits[row]
40        print("Selected: \(selectedFruit)")
41    }
42}

Getting the Selected Value at Any Time

swift
1// Get the currently selected row index
2let selectedRow = pickerView.selectedRow(inComponent: 0)
3let selectedValue = fruits[selectedRow]
4print("Currently selected: \(selectedValue)")
5
6// Useful in a button action
7@objc func confirmButtonTapped() {
8    let row = pickerView.selectedRow(inComponent: 0)
9    let value = fruits[row]
10    // Use the selected value
11    showAlert(message: "You chose: \(value)")
12}

Multi-Component Picker

swift
1class DatePickerController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
2
3    let pickerView = UIPickerView()
4    let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
5                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
6    let years = Array(2020...2030).map { String($0) }
7
8    func numberOfComponents(in pickerView: UIPickerView) -> Int {
9        return 2  // Month and Year
10    }
11
12    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
13        return component == 0 ? months.count : years.count
14    }
15
16    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
17        return component == 0 ? months[row] : years[row]
18    }
19
20    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
21        let monthRow = pickerView.selectedRow(inComponent: 0)
22        let yearRow = pickerView.selectedRow(inComponent: 1)
23        let selected = "\(months[monthRow]) \(years[yearRow])"
24        print("Selected: \(selected)")  // e.g., "Mar 2025"
25    }
26}

Setting a Default Selection

swift
1override func viewDidLoad() {
2    super.viewDidLoad()
3
4    pickerView.delegate = self
5    pickerView.dataSource = self
6
7    // Set default selection to "Cherry" (index 2)
8    pickerView.selectRow(2, inComponent: 0, animated: false)
9
10    // Note: selectRow does NOT trigger didSelectRow delegate method
11    // If you need to update UI, call your update method manually
12}

Using UIPickerView with UITextField

A common pattern is presenting the picker as the input view for a text field.

swift
1class FormViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
2
3    let textField = UITextField()
4    let pickerView = UIPickerView()
5    let options = ["Small", "Medium", "Large", "Extra Large"]
6
7    override func viewDidLoad() {
8        super.viewDidLoad()
9
10        pickerView.delegate = self
11        pickerView.dataSource = self
12
13        // Use picker as the text field's input view
14        textField.inputView = pickerView
15
16        // Add a toolbar with a Done button
17        let toolbar = UIToolbar()
18        toolbar.sizeToFit()
19        let doneButton = UIBarButtonItem(title: "Done", style: .done,
20                                          target: self, action: #selector(doneTapped))
21        let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
22        toolbar.setItems([spacer, doneButton], animated: false)
23        textField.inputAccessoryView = toolbar
24    }
25
26    @objc func doneTapped() {
27        let row = pickerView.selectedRow(inComponent: 0)
28        textField.text = options[row]
29        textField.resignFirstResponder()
30    }
31
32    // ... delegate/dataSource methods same as above
33}

Common Pitfalls

  • Calling selectedRow before the picker is displayed: selectedRow(inComponent:) returns 0 (first row) before the user interacts with the picker. If 0 is not a valid default, call selectRow(_:inComponent:animated:) in viewDidLoad to set an explicit default.
  • Forgetting that selectRow does not trigger the delegate: Programmatically calling selectRow(_:inComponent:animated:) does not call didSelectRow. If you need to update UI or state when setting a default, call your update logic manually after selectRow.
  • Index out of range when data source changes: If you update the data source array (e.g., filter options) without reloading the picker, the selected row index may exceed the new array bounds. Call pickerView.reloadAllComponents() after changing data, then validate the selected index.
  • Not setting both delegate and dataSource: UIPickerView requires both delegate and dataSource to be set. Missing either results in an empty picker or crashes. Both protocols must be adopted by the same or different objects.
  • Using UIDatePicker instead of UIPickerView for dates: For date/time selection, use UIDatePicker which provides a native date interface and returns a Date object directly via .date property. Only use UIPickerView for custom non-date option lists.

Summary

  • Call pickerView.selectedRow(inComponent:) to get the selected row index, then look up the value in your data array
  • Implement both UIPickerViewDelegate and UIPickerViewDataSource protocols
  • Use didSelectRow delegate method to respond to user selections in real time
  • Use selectRow(_:inComponent:animated:) to set a default — but call update logic manually since it does not trigger the delegate
  • Present the picker as textField.inputView for form-style interfaces

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.