Today I'd like to try to make a part of an application that after show an alert perform a segue ONLY if the user press on the "Yes" alert's button.
To explain me better I'd like that the application will show an aller that say "Are you sure to return to Home?" and it will have two Botton: "Yes" and "No". If the user press no nothing happen, if the user press yes the application perform a segue. The problem is that I don't know how to do it.
I try to write some code line but it doesn't work.
func Alert (TITLE: String, MESSAGE: String) -> Bool()
{
var X = false
let Alert = UIAlertController(title: TITLE, message: MESSAGE, preferredStyle: UIAlertControllerStyle.alert)
Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { (Action) in
X = true
Alert.dismiss(animated: true, completion: nil)
}))
self.present(Alert, animated: true, completion: nil)
Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(Alert, animated: true, completion: nil)
return X
}
#IBAction func ButtonAct(_ sender: Any) //This happen if you click the botton on the screen of the iPhone
{
if Alert (TITLE: "Return to Home", MESSAGE: "Are you sure to return Home?")
{performSegue(withIdentifier: "Segue", sender: self)}
}
Thank you for you Help
There are several problems with your code:
No part of your code is calling the #IBAction method, that is why the segue is not being performed. The alert controller only provides you with completion handlers; there is no target/action mechanism like with UIButton.
The boolean return value is determined inside the action's completion handler, asynchronously. Your function returns right away the value false, before the user has had a chance to chose. Things happen in this order:
Call alert()
Function presents UIAlertController
Function returns false
(very many milliseconds pass)
User taps "YES"
Completion handler is executes and x is set to true, but the alert() method has already returned false.
You are presenting the alert twice, once after adding each action. You need to add both actions and then present it only once.
Please use standard capitalization in your code.
Try something like this:
func alert (title: String, message: String, completion: ((Bool) -> Void)) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (action) in
alertController.dismiss(animated: true, completion: nil)
completion(true) // true signals "YES"
}))
alertController.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: { (action) in
alertController.dismiss(animated: true, completion: nil)
completion(false) // false singals "NO"
}))
self.present(alertController, animated: true, completion: nil)
}
...and call it like this:
alert(title: "Hi", message: "Want to proceed?", completion: { result in
if result {
self.performSegue(withIdentifier: "Segue", sender: self)
}
})
Related
I've few buttons, clicking on these buttons present same alert. I've to handle each button click separately so I need to pass different handlers to each of these alerts. How do I do it?
I've searched for solutions but I can't find what I'm looking for, or may be It's there but I'm not able to understand it.
Following is my code snippet. Inside this function I can get which button is clicked but I'm not able to figure out how to call different handlers and pass them alert.title.
I hope someone can point me in right direction.
#IBAction func buttonClicked(_ sender: UIButton) {
let alert = UIAlertController(title: "Select Value", message: nil, preferredStyle: .actionSheet)
for list in self.listValue {
alert.addAction(UIAlertAction(title: list.value, style: .default, handler: { _ in
// How do I call different handlers here?
// I'll need to retrieve alert.title in these handlers
}))
}
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
self.present(alert, animated: false, completion: nil)
}
It's not totally clear what you're asking, but if you are trying to figure out which button was pressed so that you can execute different methods for each one you can do something like this:
#IBAction func buttonClicked(_ sender: UIButton) {
let alert = UIAlertController(title: "Select Value", message: nil, preferredStyle: .actionSheet)
for list in self.listValue {
alert.addAction(UIAlertAction(title: list.value, style: .default, handler: { (action) in
// How do I call different handlers here?
// I'll need to retrieve alert.title in these handlers
switch action.title {
case "Value A":
print("It's Value A")
case "Value B":
print("It's Value B")
default:
print("We didn't implement anything for this value")
}
}))
}
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
self.present(alert, animated: false, completion: nil)
}
I have written code for an alert to appear when the input in one of my UITextFields is less than 1050. It successfully appears when the inputs satisfies that, but after I press "OK" it instantly re-appears.
Below is the code in the viewDidLoad function:
override func viewDidLoad(){
super.viewDidLoad()
alert = UIAlertController(title: "Error", message: "Please enter an exit width value greater than 1050", preferredStyle: UIAlertControllerStyle.Alert)
let okay = UIAlertAction(title: "OK", style: UIAlertActionStyle.Destructive, handler: valueCalc)
alert.addAction(okay)
}
Then I have in my valueCalc function (which is called when a button is tapped):
#IBAction func valueCalc(sender: AnyObject){
if(Int(mmText.text!)! < 1050){ //mmText is an UITextField
self.presentViewController(alert, animated: true, completion: nil)
}
}
According to your line of code
let okay = UIAlertAction(title: "OK", style: UIAlertActionStyle.Destructive, handler: valueCalc)
Your handler name valueCalc is called when you press OK.
Again the value is calculated which when come out be less then the specified characters shows back you the alert.
Instead of that, replace this line in your code -
let okay = UIAlertAction(title: "OK", style: UIAlertActionStyle.Destructive, handler: handlerMethod)
and add this method to your code
func handlerMethod() {
//handle your action here after ok is pressed for e.g if you wanna just dismiss the alert then write
dismissViewControllerAnimated(true, completion: nil)
}
You have the handler argument for your UIAlertAction set to valueCalc. Therefore, whenever the user taps "OK", the method valueCalc gets run again, and since the value is (presumably) still the same, the alert is presented right back again.
Try this
override func viewDidLoad(){
super.viewDidLoad()
alert = UIAlertController(title: "Error", message: "Please enter an exit width value greater than 1050", preferredStyle: UIAlertControllerStyle.Alert)
let okay = UIAlertAction(
title: "OK",
style: UIAlertActionStyle.Destructive) { (action) in }
}
#IBAction func valueCalc(sender: AnyObject){
if(Int(mmText.text!)! < 1050){ //mmText is an UITextField
self.presentViewController(alert, animated: true, completion: nil)
}
#IBAction func addButton(sender: AnyObject) {
let alert = UIAlertController(title: "New Exercise Added", message: "\(name)", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok!!", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
self.navigationController?.popToRootViewControllerAnimated(true)
self.dismissViewControllerAnimated(true, completion: {})
}
Within the IB action function of a button I have an alert, followed by some code to change to a different ViewController.
The program crashes upon reaching these lines of code after the alert:
2016-01-04 17:48:27.147 FitnessApp[60584:4080964] popToViewController:transition: called on while an existing transition or presentation is occurring; the navigation stack will not be updated.
How do I run the code to change ViewController after the transition is done?
Your biggest issue is that you don't do anything with the alert button's handler. Instead, you immediately try to do the pop and dismiss after presenting the alert.
Move the code to pop the controller into the Ok button's alert handler.
#IBAction func addButton(sender: AnyObject) {
let alert = UIAlertController(title: "New Exercise Added", message: "\(name)", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok!!", style: UIAlertActionStyle.Default, handler: {
self.navigationController?.popToRootViewControllerAnimated(true)
// You only need the pop
//self.dismissViewControllerAnimated(true, completion: {})
}))
self.presentViewController(alert, animated: true, completion: nil)
}
Note: I'm not fluent in Swift so the syntax could be off a little.
I have this function and I use it on almost all viewController´s that I have, for some reason went I push "ok" to dismiss the pop up, it switches to another viewController.
this is my function...
extension UIViewController
{
func displayAlert(title: String, message: String)
{
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction((UIAlertAction(title: "Ok", style: .Default, handler:
{ (action) -> Void in
self .dismissViewControllerAnimated(true, completion: nil)
})))
self.presentViewController(alert, animated: true, completion: nil)
}
}
any help? I'm using Xcode 7.0 beta 6 with swift 2
You don't need to dismiss the alert controller yourself. That happens automatically with your alert action. You're simply providing a closure that gets called when that "OK" action gets triggered. Just remove this line:
self.dismissViewControllerAnimated(true, completion: nil)
I wrote the following function below to display alerts through my project. Every time i check for an error in a form i display the alert when the user clicks submit. I want to simply show the alert, but not unwind the pervious segue. I want to stay at the current screen and give the user the opportunity to complete the form. Right now when the user clicks submit, it displays the alert ..but when i click the ok button to dismiss the alert it immediately unwinds the segue to the previous screen.
I have included the UIAlertViewDelegate in the class.... any ideas why this might be happening?
func displayAlert(title:String, error:String) {
var alert = UIAlertController(title: title, message: error, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { action in
self.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
Never mind.
func displayAlert(title:String, error:String) {
var alert = UIAlertController(title: title, message: error, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { action in
//comment out this line and it will still work. It will not segue back to the previous screen.
//self.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}