UIPickerView
iOS development
Swift programming
mobile app UI
Done button integration

How to make an UIPickerView with a Done button?

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

The most common way to show a UIPickerView with a Done button is not to place both controls manually on the screen. In UIKit, the standard pattern is to use the picker as a text field's inputView and a UIToolbar with a Done button as the inputAccessoryView.

Why This Pattern Works Well

When a text field becomes first responder, iOS shows its input view just like it would show the keyboard. If the input view is a picker instead of a keyboard, the user gets a native bottom-sheet style selector, and the accessory toolbar appears above it.

That gives you:

  • a familiar interaction model
  • an easy place for Done and Cancel buttons
  • automatic presentation and dismissal behavior through first responder handling

Complete Swift Example

swift
1import UIKit
2
3final class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
4    private let textField = UITextField()
5    private let pickerView = UIPickerView()
6    private let options = ["Red", "Green", "Blue"]
7
8    override func viewDidLoad() {
9        super.viewDidLoad()
10        view.backgroundColor = .systemBackground
11
12        textField.borderStyle = .roundedRect
13        textField.placeholder = "Choose a color"
14        textField.translatesAutoresizingMaskIntoConstraints = false
15        view.addSubview(textField)
16
17        NSLayoutConstraint.activate([
18            textField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
19            textField.centerYAnchor.constraint(equalTo: view.centerYAnchor),
20            textField.widthAnchor.constraint(equalToConstant: 220)
21        ])
22
23        pickerView.dataSource = self
24        pickerView.delegate = self
25
26        textField.inputView = pickerView
27        textField.inputAccessoryView = makeToolbar()
28    }
29
30    private func makeToolbar() -> UIToolbar {
31        let toolbar = UIToolbar()
32        toolbar.sizeToFit()
33
34        let flexible = UIBarButtonItem(
35            barButtonSystemItem: .flexibleSpace,
36            target: nil,
37            action: nil
38        )
39
40        let done = UIBarButtonItem(
41            barButtonSystemItem: .done,
42            target: self,
43            action: #selector(doneTapped)
44        )
45
46        toolbar.items = [flexible, done]
47        return toolbar
48    }
49
50    @objc private func doneTapped() {
51        let row = pickerView.selectedRow(inComponent: 0)
52        textField.text = options[row]
53        textField.resignFirstResponder()
54    }
55
56    func numberOfComponents(in pickerView: UIPickerView) -> Int {
57        return 1
58    }
59
60    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
61        return options.count
62    }
63
64    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
65        return options[row]
66    }
67}

This is the standard UIKit setup for a picker with a Done button.

What Each Part Does

  • 'inputView: replaces the keyboard with the picker'
  • 'inputAccessoryView: provides the toolbar above the picker'
  • 'resignFirstResponder(): dismisses the picker and toolbar'
  • 'selectedRow(inComponent:): reads the current picker choice'

This separation is important. The picker chooses the value, and the toolbar controls the interaction lifecycle.

Adding a Cancel Button

Many apps use both Cancel and Done:

swift
1let cancel = UIBarButtonItem(
2    barButtonSystemItem: .cancel,
3    target: self,
4    action: #selector(cancelTapped)
5)
6
7toolbar.items = [cancel, flexible, done]

Then implement:

swift
@objc private func cancelTapped() {
    textField.resignFirstResponder()
}

This is useful when you do not want to commit the selection automatically.

If the Picker Is Not Tied to a Text Field

You can also place a UIPickerView directly in your layout and put a toolbar or button above it with Auto Layout constraints. That works, but it is a different UI pattern. The inputView approach is usually preferred for form-like data entry because it behaves like a controlled replacement for the keyboard.

Choose based on the interaction:

  • form field selection: use inputView
  • always-visible picker area: place it directly in the view hierarchy

Delegate and Data Source Basics

A picker needs two categories of methods:

  • data source methods for component count and row count
  • delegate methods for titles or custom views and selection handling

The minimum setup for a basic string picker is:

  • 'numberOfComponents'
  • 'numberOfRowsInComponent'
  • 'titleForRow'

You can also use didSelectRow if you want live updates before the user taps Done.

Common Pitfalls

The biggest mistake is creating the picker and toolbar but forgetting to assign them to inputView and inputAccessoryView. In that case, tapping the text field still shows the normal keyboard.

Another mistake is forgetting resignFirstResponder() in the Done action. Without it, the picker stays visible.

People also read the selected row before the picker has valid data, usually because the delegate or data source was never assigned.

Finally, if the text field should not allow typed text, do not forget that the picker is replacing keyboard input conceptually. Keep the interaction consistent and avoid mixing free typing with picker-only choices unless that is truly intended.

Summary

  • The standard UIKit pattern is UITextField.inputView = pickerView.
  • Add a UIToolbar with a Done button through inputAccessoryView.
  • Use the Done action to read the selected row, update the field, and call resignFirstResponder().
  • Add Cancel if you want dismissal without committing the selection.
  • Use a directly embedded picker only when the picker should remain visible on screen.

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.