161

I'm trying to make an alert controller with message and input, and then get the value from the input. I've found many good tutorials on how to make the input text field, but I can't get the value from the alert.

HangarRash
  • 7,314
  • 5
  • 5
  • 32
ntoonio
  • 3,024
  • 4
  • 24
  • 28

5 Answers5

393

Updated for Swift 3 and above:

//1. Create the alert controller.
let alert = UIAlertController(title: "Some Title", message: "Enter a text", preferredStyle: .alert)

//2. Add the text field. You can configure it however you need.
alert.addTextField { (textField) in
    textField.text = "Some default text"
}

// 3. Grab the value from the text field, and print it when the user clicks OK.
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (_) in
    let textField = alert.textFields![0] // Force unwrapping because we know it exists.
    print("Text field: \(textField.text)")
}))

// 4. Present the alert.
self.present(alert, animated: true, completion: nil)

Swift 2.x

Assuming you want an action alert on iOS:

//1. Create the alert controller.            
var alert = UIAlertController(title: "Some Title", message: "Enter a text", preferredStyle: .Alert)

//2. Add the text field. You can configure it however you need.
alert.addTextFieldWithConfigurationHandler({ (textField) -> Void in
    textField.text = "Some default text."
})

//3. Grab the value from the text field, and print it when the user clicks OK. 
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { [weak alert] (action) -> Void in
    let textField = alert.textFields![0] as UITextField
    println("Text field: \(textField.text)")
}))

// 4. Present the alert.
self.presentViewController(alert, animated: true, completion: nil)
Andy Ibanez
  • 12,104
  • 9
  • 65
  • 100
  • Hi @AndyIbanez I'm trying to implement your code on my app, however its stating the error "Use of undeclared identifier var" I'm new to Xcode so apologies if this is a basic error on my behalf – Sjharrison Feb 28 '15 at 21:23
  • @Sjharrison My code is for Swift. The only reason I can think of that would cause you troubles with the `var` keyword is if you were writing in Objective-C. – Andy Ibanez Feb 28 '15 at 21:25
  • Ahh i see! yeah I'm using Xcode, only been doing this a few hours so over tired and still learning! – Sjharrison Feb 28 '15 at 21:31
  • 1
    Can anyone explain why the `[weak alert]`? I'm looking at Swift 3. – Andrej Jan 18 '17 at 23:59
  • @Andrej It's to avoid leaking memory. To better understand, read about memory management in Swift. – Andy Ibanez Jan 24 '17 at 02:50
  • Worked after small modifications. Thanks, Buddy. – AbaEesa Apr 03 '17 at 13:09
  • @RAISIQBAL What modifications did you do? Please let me know to see if updating this answer will be necessary. – Andy Ibanez Apr 03 '17 at 21:39
  • 5
    For Swift 3 alert in step 3. is optional, needed "?" `let textField = alert?.textFields![0] // Force unwrapping because we know it exists.` `print("Text field: \(textField?.text)")` – James Apr 06 '17 at 19:40
  • Maybe you can add cancel action as well in your answer. – Umit Kaya Jun 14 '17 at 14:22
  • Many people have tried to add the Cancel button to this answer. Please stop trying to do that. If it gets approved, I will revert it. The answer as it is already addresses the author's question. Let adding the Cancel button be an exercise for the reader of this answer. – Andy Ibanez Feb 12 '18 at 16:21
  • Don't forget the iPad popover: // iPad popOver: if let popoverController = alert.popoverPresentationController { popoverController.sourceView = self.view popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0) popoverController.permittedArrowDirections = [] } – FrugalResolution May 04 '21 at 02:49
52

Swift 5

You can use the below extension for your convenience.

Usage inside a ViewController:

showInputDialog(title: "Add number",
                subtitle: "Please enter the new number below.",
                actionTitle: "Add",
                cancelTitle: "Cancel",
                inputPlaceholder: "New number",
                inputKeyboardType: .numberPad, actionHandler:
                        { (input:String?) in
                            print("The new number is \(input ?? "")")
                        })

The extension code:

extension UIViewController {
    func showInputDialog(title:String? = nil,
                         subtitle:String? = nil,
                         actionTitle:String? = "Add",
                         cancelTitle:String? = "Cancel",
                         inputPlaceholder:String? = nil,
                         inputKeyboardType:UIKeyboardType = UIKeyboardType.default,
                         cancelHandler: ((UIAlertAction) -> Swift.Void)? = nil,
                         actionHandler: ((_ text: String?) -> Void)? = nil) {
        
        let alert = UIAlertController(title: title, message: subtitle, preferredStyle: .alert)
        alert.addTextField { (textField:UITextField) in
            textField.placeholder = inputPlaceholder
            textField.keyboardType = inputKeyboardType
        }
        alert.addAction(UIAlertAction(title: actionTitle, style: .default, handler: { (action:UIAlertAction) in
            guard let textField =  alert.textFields?.first else {
                actionHandler?(nil)
                return
            }
            actionHandler?(textField.text)
        }))
        alert.addAction(UIAlertAction(title: cancelTitle, style: .cancel, handler: cancelHandler))
        
        self.present(alert, animated: true, completion: nil)
    }
}
Ethan Allen
  • 14,425
  • 24
  • 101
  • 194
Gunhan
  • 6,807
  • 3
  • 43
  • 37
  • just note that if you are going to present "Add" action make sure the style if "default" not "destructive" -- alert.addAction(UIAlertAction(title: actionTitle, style: .default ... – Bishal Ghimire Jul 13 '19 at 10:46
  • @Gunhan How to assign delegate for the textfield? – Vaibhav Jhaveri Oct 09 '20 at 10:41
  • @VaibhavJhaveri just add one more parameter to the function e.g. delegate: UITextFieldDelegate? = nil, and inside the function where we add the textfield assign it e.g. textField.delegate = delegate – Gunhan Oct 09 '20 at 10:49
  • @Gunhan That worked. However, the text field is displayed with it being the first responder. I want to turn that off. how can I do that? I want to open custom view when I click on the textfield – Vaibhav Jhaveri Oct 09 '20 at 11:08
24

In Swift5 ans Xcode 10

Add two textfields with Save and Cancel actions and read TextFields text data

func alertWithTF() {
    //Step : 1
    let alert = UIAlertController(title: "Great Title", message: "Please input something", preferredStyle: UIAlertController.Style.alert )
    //Step : 2
    let save = UIAlertAction(title: "Save", style: .default) { (alertAction) in
        let textField = alert.textFields![0] as UITextField
        let textField2 = alert.textFields![1] as UITextField
        if textField.text != "" {
            //Read TextFields text data
            print(textField.text!)
            print("TF 1 : \(textField.text!)")
        } else {
            print("TF 1 is Empty...")
        }

        if textField2.text != "" {
            print(textField2.text!)
            print("TF 2 : \(textField2.text!)")
        } else {
            print("TF 2 is Empty...")
        }
    }

    //Step : 3
    //For first TF
    alert.addTextField { (textField) in
        textField.placeholder = "Enter your first name"
        textField.textColor = .red
    }
    //For second TF
    alert.addTextField { (textField) in
        textField.placeholder = "Enter your last name"
        textField.textColor = .blue
    }

    //Step : 4
    alert.addAction(save)
    //Cancel action
    let cancel = UIAlertAction(title: "Cancel", style: .default) { (alertAction) in }
    alert.addAction(cancel)
    //OR single line action
    //alert.addAction(UIAlertAction(title: "Cancel", style: .default) { (alertAction) in })

    self.present(alert, animated:true, completion: nil)

}

For more explanation https://medium.com/@chan.henryk/alert-controller-with-text-field-in-swift-3-bda7ac06026c

Naresh
  • 16,698
  • 6
  • 112
  • 113
10

Swift version: 5.+

Create a new TextField variable in current scope and assign it to alertTextField in alert.addTextField completion handler. Use textField's value inside UIAlertAction completion handler.

@IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
          //Variable to store alertTextField
            var textField = UITextField()
            
            let alert = UIAlertController(title: "Add new item", message: "", preferredStyle: .alert)
            alert.addTextField { alertTextField in
                alertTextField.placeholder = "Create new item"
                
                //Copy alertTextField in local variable to use in current block of code
                textField = alertTextField
            }
            
            let action = UIAlertAction(title: "Add item", style: .default) { action in
                //Prints the alertTextField's value
                print(textField.text!)
            }
            
            alert.addAction(action)
            present(alert, animated: true, completion: nil)
        }
1
let ac = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
ac.addTextField()

let submitAction = UIAlertAction(title: "Submit", style: .default) { [weak self, weak ac] action in
    guard let wordToget = ac?.textFields?[0].text else { return }
    //here you can do what you need like
    print(wordToget)
}

ac.addAction(submitAction)
present(ac, animated: true)