Pop Alert will change view controller - ios

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)

Related

How can I perform a segue after receive an alert answer

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

swift: view is not in the view hierarchy

I'm having a homeView which is the initial view to appear when app launches. In its viewWillAppear() method I check if the user is logged in. If not, he's redirected to login page and if he's not yet registered he'll be directed to sign-up page. I get an error when user clicks the sign-up button. The signUPView appears but it gives a warning that Attempt to present loginViewController on signupViewController whose view is not in the window hierarchy. I have show detail segues between sign-up and login views.
I'm performing the segue after uialert is presented.
I got solutions to put the code in viewDidAppear or ViewWillAppear method but I'm presenting the viewControllers upon button press. So I can't use these methods.
I have searched for a lot of solutions but unable to get the right one.
Please help!
Thank you.
segue triggering code from sign-up :
dispatch_async(dispatch_get_main_queue()) {
if self.registerSuccess == true {
let alert = UIAlertController(title: "Registered!", message: "You have registered successfully!", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
self.nameTextField.text = ""
self.emailTextField.text = ""
self.passwordTextField.text = ""
self.performSegueWithIdentifier("loginSegue", sender: self)
}))
self.presentViewController(alert, animated: true, completion: nil)
} else {
let alert = UIAlertController(title: "Registration Failed!", message: "Please try again", 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)
}
}
screenshot of my storyboard

How do I pop to RootViewController when an alert is dismissed?

#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.

UIAlertController Error When called in a modal presented view controller in swift

I have a view controller which is modally presented and when i run UIAlertController, keep getting a error message . how can i work around this.
the alert is trigged from a button which checks a text field is empty or not.
#IBAction func registerAction(sender: AnyObject) {
if(userEmail.isEmpty){
alertMessage("Fields Are Empty")
}
}
func alertMessage(userMessage:String){
var myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
myAlert.addAction(okAction)
self.presentViewController(myAlert, animated: true, completion: nil)
}
Error when i run the alert
Warning: Attempt to present <UIAlertController: 0x7f9bbb9060d0> on <AlertApp.CustomSignupVC: 0x7f9bb94accb0> which is already presenting <UIAlertController: 0x7f9bbb926660>
Try to add it in main operation queue.
dispatch_async(dispatch_get_main_queue()) {
self.presentViewController(myAlert, animated: true, completion: nil)
}
Check this relative question : Presenting a view controller modally from an action sheet's delegate in iOS8 - iOS10

Issues with displaying Alerts in Swift (After clicking "Ok", it unwinds segue

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

Resources