108

I am trying to show a UIAlertController with a UITextView. When I add the line:

    //Add text field
    alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
    }        

I get a Runtime error:

fatal error: unexpectedly found nil while unwrapping an Optional value

    let alertController: UIAlertController = UIAlertController(title: "Find image", message: "Search for image", preferredStyle: .Alert)

    //cancel button
    let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in
        //cancel code
    }
    alertController.addAction(cancelAction)

    //Create an optional action
    let nextAction: UIAlertAction = UIAlertAction(title: "Search", style: .Default) { action -> Void in
        let text = (alertController.textFields?.first as! UITextField).text
        println("You entered \(text)")
    }
    alertController.addAction(nextAction)

    //Add text field
    alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
        textField.textColor = UIColor.greenColor()
    }
    //Present the AlertController
    presentViewController(alertController, animated: true, completion: nil)

This is presented inside my ViewController via an IBAction.

I have downloaded the code from here and it works fine. I copied and pasted that method into my code and it breaks. The presence of self on the last line has no impact.

Naresh
  • 16,698
  • 6
  • 112
  • 113
Quintin Balsdon
  • 5,484
  • 10
  • 54
  • 95

14 Answers14

216

Swift 5.1

alert.addTextField { (textField) in
    textField.placeholder = "Enter First Name"
}

Use this code, I am running this code in my app successfully.

@IBAction func addButtonClicked(sender : AnyObject){
    let alertController = UIAlertController(title: "Add New Name", message: "", preferredStyle: UIAlertControllerStyle.Alert)
    alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
        textField.placeholder = "Enter Second Name"
    }
    let saveAction = UIAlertAction(title: "Save", style: UIAlertActionStyle.Default, handler: { alert -> Void in
        let firstTextField = alertController.textFields![0] as UITextField
        let secondTextField = alertController.textFields![1] as UITextField
    })
    let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Default, handler: {
        (action : UIAlertAction!) -> Void in })
    alertController.addTextFieldWithConfigurationHandler { (textField : UITextField!) -> Void in
        textField.placeholder = "Enter First Name"
    }
    
    alertController.addAction(saveAction)
    alertController.addAction(cancelAction)
    
    self.presentViewController(alertController, animated: true, completion: nil)
}

Edited: Swift 3.0 version

@IBAction func addButtonClicked(_ sender: UIButton){
    let alertController = UIAlertController(title: "Add New Name", message: "", preferredStyle: .alert)
    alertController.addTextField { (textField : UITextField!) -> Void in
        textField.placeholder = "Enter Second Name"
    }
    let saveAction = UIAlertAction(title: "Save", style: .default, handler: { alert -> Void in
        let firstTextField = alertController.textFields![0] as UITextField
        let secondTextField = alertController.textFields![1] as UITextField
        print("firstName \(firstTextField.text), secondName \(secondTextField.text)")
    })
    let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: { (action : UIAlertAction!) -> Void in })
    alertController.addTextField { (textField : UITextField!) -> Void in
        textField.placeholder = "Enter First Name"
    }

    alertController.addAction(saveAction)
    alertController.addAction(cancelAction)
    
    self.present(alertController, animated: true, completion: nil)
}
Community
  • 1
  • 1
Himanshu Mahajan
  • 4,779
  • 2
  • 36
  • 29
23

To add a text field in Swift 3.0:

let alertController = UIAlertController(title: "Title", message: "", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Save", style: .default, handler: { alert -> Void in
    let textField = alertController.textFields![0] as UITextField
    // do something with textField
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alertController.addTextField(configurationHandler: {(textField : UITextField!) -> Void in
    textField.placeholder = "Search"
})   
self.present(alertController, animated: true, completion: nil)
LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174
Meagan S.
  • 974
  • 9
  • 11
16

Solution:

Swift 4.2

Try the following lines and see if it works:

let alertController = UIAlertController(title: "Add New Name", message: "", preferredStyle: .alert)

alertController.addTextField { (textField : UITextField!) -> Void in
    textField.placeholder = "Enter Second Name"
}

let saveAction = UIAlertAction(title: "Save", style: .default, handler: { alert -> Void in
    let firstTextField = alertController.textFields![0] as UITextField
    let secondTextField = alertController.textFields![1] as UITextField
})

let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil )

alertController.addTextField { (textField : UITextField!) -> Void in
    textField.placeholder = "Enter First Name"
}

alertController.addAction(saveAction)
alertController.addAction(cancelAction)

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

Hope it helps.

pkamb
  • 33,281
  • 23
  • 160
  • 191
Ümañg ßürmån
  • 9,695
  • 4
  • 24
  • 41
  • Is the order of the two `alertController.addTextField` correct? It seems like "Second Name" would appear above "First Name". – benc Jun 10 '19 at 08:39
12

So I started checking to see what could possibly have been different in my code to the working code. I noticed that my ViewController extends

UITextFieldDelegate

Which apparently means that I need to set the delegate of any child UITextView:

alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
    searchTextField = textField
    searchTextField?.delegate = self //REQUIRED
    searchTextField?.placeholder = "Enter your search terms"
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Quintin Balsdon
  • 5,484
  • 10
  • 54
  • 95
7

How to add textField to AlertView? Let's keep it short and simple.

This works for Swift 3.0 and above.

var nameField: UITextField?
let alertController = UIAlertController(title: "Add Number", message: nil, preferredStyle: .alert)
// Add textfield to alert view
alertController.addTextField { (textField) in
    nameField = textField
}

First, you instantiate an object of UIAlertController and then you add a text field to it by accessing addTextField member of UIAlertController class.

Maihan Nijat
  • 9,054
  • 11
  • 62
  • 110
5

UIAlertController with UITextfield in latest Apple Swift version 5.1.3

Create a lazy variable of UIAlertController in your UIViewController , Add UITextFieldDelegate , Show Alert on UIButton Action :

class  YourViewController: UIViewController,UITextFieldDelegate {

    //Create Alert Controller Object here
    lazy var alertEmailAddEditView:UIAlertController = {

        let alert = UIAlertController(title:"My App", message: "Customize Add/Edit Email Pop Up", preferredStyle:UIAlertController.Style.alert)

        //ADD TEXT FIELD (YOU CAN ADD MULTIPLE TEXTFILED AS WELL)
        alert.addTextField { (textField : UITextField!) in
            textField.placeholder = "Enter  emails"
            textField.delegate = self
        }

        //SAVE BUTTON
        let save = UIAlertAction(title: "Save", style: UIAlertAction.Style.default, handler: { saveAction -> Void in
            let textField = alert.textFields![0] as UITextField
            print("value entered by user in our textfield is: \(textField.text)")
        })
        //CANCEL BUTTON
        let cancel = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.default, handler: {
            (action : UIAlertAction!) -> Void in })


        alert.addAction(save)
        alert.addAction(cancel)

        return alert
    }()


    //MARK:- UIButton Action for showing Alert Controller
    @objc func buttonClicked(btn:UIButton){
        self.present(alertEmailAddEditView, animated: true, completion: nil)
    }

    //MARK:- UITextFieldDelegate
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
}

Happy Coding!! :)

Abhimanyu Daspan
  • 1,095
  • 16
  • 20
4

To add alertController with one textField (Swift 5)

func openAlert(){
    let alertController = UIAlertController(title: "Title", message: "", preferredStyle: .alert)
    alertController.addTextField { (textField : UITextField!) -> Void in
        textField.placeholder = "Enter name"
    }

    let saveAction = UIAlertAction(title: kAlertConfirm, style: .default, handler: { alert -> Void in
        if let textField = alertController.textFields?[0] {
            if textField.text!.count > 0 {
                print("Text :: \(textField.text ?? "")")
            }
        }
    })

    let cancelAction = UIAlertAction(title: kAlertCancel, style: .default, handler: {
        (action : UIAlertAction!) -> Void in })

    alertController.addAction(cancelAction)
    alertController.addAction(saveAction)

    alertController.preferredAction = saveAction

    self.present(alertController, animated: true, completion: nil)
}
Hardik Thakkar
  • 15,269
  • 2
  • 94
  • 81
3

For Swift 4.0, You can use this sample of code succesfully tested in my project:

@IBAction func withdrawTapped(_ sender: UIButton) {

  let alertController = UIAlertController(title: "Token withdraw", message: "", preferredStyle: .alert)

  let withdrawAction = UIAlertAction(title: "Withdraw", style: .default) { (aciton) in

    let text = alertController.textFields!.first!.text!

    if !text.isEmpty {
      self.presentAlert(
        title: "Succesful", 
        message: "You made request for withdraw \(textField.text) tokens")
    }
  }

  let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) in
  }

  alertController.addTextField { (textField) in
    textField.placeholder = "999"
    textField.keyboardType = .decimalPad
  }

  alertController.addAction(withdrawAction)
  alertController.addAction(cancelAction)

  self.present(alertController, animated: true, completion: nil)
}
Oleh Veheria
  • 412
  • 5
  • 13
3

In Swift 4.2 and Xcode 10.1

Alert with two Textfields and Read TextField text data and present alert on top of all views.

func alertWithTF(title: String, message: String) {
    //Step : 1
    let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)

    //Step : 2
    alert.addAction (UIAlertAction(title: "Save", style: .default) { (alertAction) in
        let textField = alert.textFields![0]
        let textField2 = alert.textFields![1]
        if textField.text != "" {
            //Read textfield data
            print(textField.text!)
            print("TF 1 : \(textField.text!)")
        } else {
            print("TF 1 is Empty...")
        }
        if textField2.text != "" {
            //Read textfield data
            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
    }

    //Cancel action
    alert.addAction(UIAlertAction(title: "Cancel", style: .default) { (alertAction) in })
   self.present(alert, animated:true, completion: nil)

}

If you want to present aleert on top of all views.

Here from above code remove this last line self.present(alert, animated:true, completion: nil) and add below code.

//Present alert on top of all views.
let alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindowLevelAlert + 1

alertWindow.makeKeyAndVisible()

alertWindow.rootViewController?.present(alert, animated:true, completion: nil)

Now call like this

alertWithTF(title: "This is title", message: "This is message")
Naresh
  • 16,698
  • 6
  • 112
  • 113
1

Great answer a slight modification to show how the textfield can be used:

func addRow (row: Int, bodin: String, flag: Int) {
    let alertController = UIAlertController(title: bodin, message: "", preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Save", style: .default, handler: {
        alert -> Void in
        _ = alertController.textFields![0] as UITextField

    }))
    alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

    alertController.addTextField(configurationHandler: {(textField : UITextField!) -> Void in
        switch flag {
        case 0:
            textField.keyboardType = UIKeyboardType.phonePad
            textField.placeholder = "Enter Number"
        case 1:
            textField.keyboardType = UIKeyboardType.emailAddress
            textField.placeholder = "Enter Email"
        default:
            break
        }

    })
Jeremy Andrews
  • 807
  • 12
  • 17
1

add TextField to UIAlertController and TextField text Display on UILabel in Swift

let alert = UIAlertController(title: "Alert", message: "", preferredStyle: .alert)

alert.addTextField { (textField) in
textField.placeholder = "First Name"
}
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (_) in
let textField = alert?.textFields![0]
self.label.text = textField?.text  }))

self.present(alert, animated: true, completion: nil)
ram
  • 69
  • 1
  • 2
1

Swift5

First class conforms to the UITextFieldDelegate , then create new textField property

    private var myTextField : UITextField?

    // now where u want to add code
    let alertContoller = UIAlertController.init(title: "Add", message: "My message to user", preferredStyle: .alert)
    alertContoller.addTextField { (textField) in
        // make sure your outside any property should be accessed with self here
        self.myTextField = textField
        //Important step assign textfield delegate to self
        self.myTextField?.delegate = self 
        self.myTextField?.placeholder = self.textFieldPlaceholderText
    }
    let action = UIAlertAction.init(title: "Ok", style: .default) { action in
        print("Alert tapped")
    }
    alertContoller.addAction(action)
    present(alertContoller, animated: true, completion:nil)

Thanks

dakrawat
  • 279
  • 2
  • 9
  • This is what I was looking for. I wanted to restrict characters within the text field inside the alert controller. I like your idea of declaring the `textField` outside the controller. That way I can use `textField` `shouldChangeCharactersInRange`. Really good idea. Thanks! – Phontaine Judd Apr 08 '21 at 06:25
0
private func showLoginAlert() {
    let loginAlert = UIAlertController(title: "Login Using Credentials", message: nil, preferredStyle: .alert)
    loginAlert.view.tintColor = .systemBlue

    loginAlert.addTextField { usernameField in
        usernameField.font = .systemFont(ofSize: 17.0)
        usernameField.placeholder = "Username"
    }
    loginAlert.addTextField { passwordField in
        passwordField.font = .systemFont(ofSize: 17.0)
        passwordField.isSecureTextEntry = true
        passwordField.placeholder = "Password"
    }

    let cancelAction = UIAlertAction(title: "Cancel",
                                     style: .destructive,
                                     handler: { _ in
                                        // self.handleUsernamePasswordCanceled(loginAlert: loginAlert)
    })
    loginAlert.addAction(cancelAction)

    let loginAction = UIAlertAction(title: "Login",
                                    style: .default,
                                    handler: { _ in
                                        // self.handleUsernamePasswordEntered(loginAlert: loginAlert)
    })
    loginAlert.addAction(loginAction)
    loginAlert.preferredAction = loginAction
    present(loginAlert, animated: true, completion: nil)
}

Swift 5

Debaprio B
  • 503
  • 7
  • 9
-1

2023. Simple, modern, clean example, with realistic checking and thread handling.

let alert = UIAlertController(title: "", message: "Enter...", preferredStyle: .alert)

alert.addTextField{ tf in
    tf.placeholder = "Height"
    tf.keyboardType = .decimalPad
}

alert.addAction(UIAlertAction(title: "OK", style: .default) { [weak self] _ in
    
    guard let self = self else { return }
    DispatchQueue.main.async {
        
        guard let tff = alert.textFields else { return }
        let tf = tff[0]
        self.test(tf.text)
    }
})

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

And you'd have a function to process the input ...

func test(_ y: String?) {
    
    print("entered year \(String(describing: y))")
}
Fattie
  • 27,874
  • 70
  • 431
  • 719