How to make UIAlertController modal in iOS 9.3? The dialog box comes up, looks right and works correctly, but the app doesn't wait for an answer. I'm using #present(_,animated:,completion:) to bring it up. Even the completion block runs before the user can do anything. There is some API from versions long after 9.3 that might help if I was targeting later versions, but I'm not. I have read a bunch of articles on the net: they all say this easy, and it is easy, but it isn't modal.
Accepted Reply
The alert completion block is run as soon as alert has been displayed, not waiting for user answer.
You need to put actions that require user interaction in the UIAlertAction handlers.
Here is an example of an alert, with request for text entry for a name. We wait for entry validated to close the alertCalled when tapping a button.
@objc func alertTextFieldDidChange(_ sender: UITextField) {
alert?.actions[0].isEnabled = sender.text!.count > 0
}
@IBAction func testAlert(_ sender: Any) {
//1. Create the alert controller.
alert = UIAlertController(title: "Recherche de la Ville", message: "Nom de la ville ", preferredStyle: .alert)
//2. Add the text field.
alert?.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = ""
textField.keyboardType = UIKeyboardType.emailAddress
// alertTextFieldDidChange activate searchButton
textField.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
})
//3. Grab the value from the text field.
let yesAction = UIAlertAction(title: "Search", style: .default, handler: { (action) -> Void in
let textField = self.alert?.textFields![0]
if textField?.text! == "" {
print("empty")
} else {
print("not empty", textField?.text! ?? "")
}
})
yesAction.isEnabled = false
alert?.addAction(yesAction)
// 4. Present the alert.
self.present(alert!, animated: true, completion: nil)
}
If you replace line 32 by
self.present(alert!, animated: true, completion: { print("fired immediately") })
You will see that completion block is executed before any user interaction
Replies
The alert completion block is run as soon as alert has been displayed, not waiting for user answer.
You need to put actions that require user interaction in the UIAlertAction handlers.
Here is an example of an alert, with request for text entry for a name. We wait for entry validated to close the alertCalled when tapping a button.
@objc func alertTextFieldDidChange(_ sender: UITextField) {
alert?.actions[0].isEnabled = sender.text!.count > 0
}
@IBAction func testAlert(_ sender: Any) {
//1. Create the alert controller.
alert = UIAlertController(title: "Recherche de la Ville", message: "Nom de la ville ", preferredStyle: .alert)
//2. Add the text field.
alert?.addTextField(configurationHandler: { (textField) -> Void in
textField.placeholder = ""
textField.keyboardType = UIKeyboardType.emailAddress
// alertTextFieldDidChange activate searchButton
textField.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
})
//3. Grab the value from the text field.
let yesAction = UIAlertAction(title: "Search", style: .default, handler: { (action) -> Void in
let textField = self.alert?.textFields![0]
if textField?.text! == "" {
print("empty")
} else {
print("not empty", textField?.text! ?? "")
}
})
yesAction.isEnabled = false
alert?.addAction(yesAction)
// 4. Present the alert.
self.present(alert!, animated: true, completion: nil)
}
If you replace line 32 by
self.present(alert!, animated: true, completion: { print("fired immediately") })
You will see that completion block is executed before any user interaction
Strange, and not at all what I want, but good to know. Thank you.
not at all what I want.
So, could you explain in detail what you want ?
There is some API from versions long after 9.3
Which do you think of ?
It is a bit risky to target 9.3 or below. That's now less than 1% of users.
But you could have a test of iOS version and adapt code accordingly. Anyway, please explain what you want precisely.
If you don't need a text entry, just skip this part. The key is to use the handlers for the UIAlertAction (available since iOS 8).
Note: if
preferredStyle: .alert
Then the alert is modal.
As described in UIAlertController doc:
case alert
An alert displayed modally for the app.
What else do you need ?