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.

1
  • UITextField, rather than UITextView ? Commented Jun 10, 2019 at 8:18

14 Answers 14

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) } 
Sign up to request clarification or add additional context in comments.

1 Comment

Note there is a retain cycle in the code above (both swift 3.0 and 5.1) Notice that saveAction retains alertController and alertController retains saveAction. The solution is to declare [unowned alertController] in the saveAction code block.
24

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) 

Comments

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.

1 Comment

Is the order of the two alertController.addTextField correct? It seems like "Second Name" would appear above "First Name".
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" } 

Comments

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.

Comments

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!! :)

Comments

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) } 

Comments

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) } 

Comments

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") 

Comments

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 } }) 

Comments

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) 

Comments

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

1 Comment

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!
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

Comments

-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))") } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.