UIAlertController
Swift
iOS
text field
programming tutorial

How to get input value from a UIAlertController text field?

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

UIAlertController supports adding text fields to alert dialogs for collecting user input. To get the text value, access the textFields array inside the action handler closure after the user taps a button. The text field is added with addTextField, configured in a closure, and read back via alertController.textFields?[0].text when the user confirms.

Basic Text Input Alert

swift
1func showInputAlert() {
2    let alert = UIAlertController(
3        title: "Enter Name",
4        message: "Please enter your name below",
5        preferredStyle: .alert
6    )
7
8    // Add a text field
9    alert.addTextField { textField in
10        textField.placeholder = "Your name"
11        textField.autocapitalizationType = .words
12    }
13
14    // OK action — reads the text field value
15    let okAction = UIAlertAction(title: "OK", style: .default) { _ in
16        let name = alert.textFields?[0].text ?? ""
17        print("User entered: \(name)")
18    }
19
20    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
21
22    alert.addAction(okAction)
23    alert.addAction(cancelAction)
24    present(alert, animated: true)
25}

The key pattern: alert.textFields?[0].text inside the action handler accesses the first text field's value after the user taps OK.

Multiple Text Fields

swift
1func showLoginAlert() {
2    let alert = UIAlertController(
3        title: "Login",
4        message: "Enter your credentials",
5        preferredStyle: .alert
6    )
7
8    // Username field
9    alert.addTextField { textField in
10        textField.placeholder = "Username"
11        textField.autocorrectionType = .no
12        textField.autocapitalizationType = .none
13    }
14
15    // Password field
16    alert.addTextField { textField in
17        textField.placeholder = "Password"
18        textField.isSecureTextEntry = true
19    }
20
21    let loginAction = UIAlertAction(title: "Login", style: .default) { _ in
22        let username = alert.textFields?[0].text ?? ""
23        let password = alert.textFields?[1].text ?? ""
24        print("Username: \(username), Password: \(password)")
25        self.authenticate(username: username, password: password)
26    }
27
28    alert.addAction(loginAction)
29    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
30    present(alert, animated: true)
31}

Text fields are indexed in the order they were added. The first addTextField call creates index 0, the second creates index 1.

Configuring Text Fields

swift
1alert.addTextField { textField in
2    // Keyboard types
3    textField.keyboardType = .emailAddress     // Email input
4    textField.keyboardType = .numberPad        // Numbers only
5    textField.keyboardType = .phonePad         // Phone number
6
7    // Text content
8    textField.text = "Default value"           // Pre-filled text
9    textField.placeholder = "Enter email"      // Placeholder
10    textField.clearButtonMode = .whileEditing  // Clear button
11
12    // Behavior
13    textField.isSecureTextEntry = true         // Password dots
14    textField.autocorrectionType = .no         // Disable autocorrect
15    textField.autocapitalizationType = .none   // No auto-caps
16    textField.returnKeyType = .done            // Return key label
17
18    // Appearance
19    textField.textColor = .label
20    textField.font = .systemFont(ofSize: 16)
21}

Disabling the OK Button Until Input Is Valid

swift
1func showValidatedAlert() {
2    let alert = UIAlertController(
3        title: "Enter Email",
4        message: nil,
5        preferredStyle: .alert
6    )
7
8    alert.addTextField { textField in
9        textField.placeholder = "[email protected]"
10        textField.keyboardType = .emailAddress
11
12        // Observe text changes to enable/disable OK button
13        NotificationCenter.default.addObserver(
14            forName: UITextField.textDidChangeNotification,
15            object: textField,
16            queue: .main
17        ) { _ in
18            let text = textField.text ?? ""
19            alert.actions.first?.isEnabled = text.contains("@") && text.contains(".")
20        }
21    }
22
23    let okAction = UIAlertAction(title: "OK", style: .default) { _ in
24        let email = alert.textFields?[0].text ?? ""
25        print("Email: \(email)")
26    }
27    okAction.isEnabled = false // Start disabled
28
29    alert.addAction(okAction)
30    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
31    present(alert, animated: true)
32}

Using a Completion Handler

For reusability, wrap the alert in a function with a completion handler:

swift
1func promptForInput(
2    title: String,
3    message: String?,
4    placeholder: String?,
5    on viewController: UIViewController,
6    completion: @escaping (String?) -> Void
7) {
8    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
9
10    alert.addTextField { textField in
11        textField.placeholder = placeholder
12    }
13
14    alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
15        completion(alert.textFields?.first?.text)
16    })
17
18    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
19        completion(nil)
20    })
21
22    viewController.present(alert, animated: true)
23}
24
25// Usage
26promptForInput(title: "New Item", message: nil, placeholder: "Item name", on: self) { input in
27    guard let name = input, !name.isEmpty else { return }
28    self.addItem(name: name)
29}

async/await Version (iOS 13+)

swift
1func promptForInput(title: String, placeholder: String?) async -> String? {
2    await withCheckedContinuation { continuation in
3        let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
4
5        alert.addTextField { $0.placeholder = placeholder }
6
7        alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
8            continuation.resume(returning: alert.textFields?.first?.text)
9        })
10
11        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
12            continuation.resume(returning: nil)
13        })
14
15        present(alert, animated: true)
16    }
17}
18
19// Usage
20Task {
21    if let name = await promptForInput(title: "Enter Name", placeholder: "Name") {
22        print("Got: \(name)")
23    }
24}

Common Pitfalls

  • Accessing textFields outside the action handler: The text fields exist when the alert is presented, but their values are only meaningful after the user taps an action button. Reading alert.textFields?[0].text immediately after present() returns the initial (empty or default) value, not what the user typed.
  • Using .actionSheet style with text fields: UIAlertController with .actionSheet style does not support text fields. Calling addTextField on an action sheet crashes at runtime. Always use .alert style for text input.
  • Forgetting optional chaining: alert.textFields is optional, and text on a UITextField is also optional. Using alert.textFields![0].text! crashes if the array is empty or text is nil. Always use alert.textFields?[0].text ?? "".
  • Strong reference to self in action closures: Action handler closures capture self strongly by default. For view controllers, this can delay deallocation. Use [weak self] in the closure if the alert handler triggers async work.
  • Not presenting on the main thread: UIAlertController must be presented from the main thread. If you call present() from a background queue (e.g., inside a network callback), the alert may not appear or may crash.

Summary

  • Add text fields with alert.addTextField { ... } and configure in the closure
  • Read values via alert.textFields?[0].text inside the action handler
  • Multiple text fields are indexed in the order added (0, 1, 2, ...)
  • Use NotificationCenter to observe text changes and disable the OK button until input is valid
  • Only .alert style supports text fields — .actionSheet does not
  • Wrap in a completion handler or async/await for reusable input prompts

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.