I'm trying to dismiss the current view controller in the completion handler of a UIAlertAction, but it is not dismissing. I have written the following code (The loading indicator is simply a loading alert controller that I dismiss when the data was successfully uploaded):
loadingIndicator.dismiss(animated: true) {
let success = UIAlertController(title: "Successfully Uploaded", message: "", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { _ in
print("Ok selected") //this is working correctly
self.dismiss(animated: true, completion: nil) //this is not
})
success.addAction(ok)
self.present(success, animated: true, completion: nil)
}
However, after clicking on "Ok" in the alert, "Ok selected" is printed but the view controller is not dismissed. Nothing else shows up in the debugger.
Try dismissing it on Main thread and also check if ViewController is presented or pushed in navigation hierarchy.
loadingIndicator.dismiss(animated: true) {
let success = UIAlertController(title: "Successfully Uploaded", message: "", preferredStyle: .alert)
let ok = UIAlertAction(title: "Ok", style: .default, handler: { _ in
DispatchQueue.main.async {
self.dismiss(animated: true, completion: nil)
// If pushed use PopViewController on navigation
// self.navigationController?.popViewController(animated: true)
}
})
success.addAction(ok)
self.present(success, animated: true, completion: nil)
}
To check if ViewController is being presented or not use self.isBeingPresented property.
Related
I want after signup the alert controller should pop up and then go the loginFirstViewController but this is not going to happen why?? it only goes to loginfirstviewcontroller instead of poping up alert controller
if error == nil {
FIRAuth.auth()?.currentUser!.sendEmailVerification(completion: { (error) in
})
print("You have successfully signed up")
//Goes to the Setup page which lets the user take a photo for their profile picture and also chose a username
let alertController = UIAlertController(title: "Successful!", message: "Email Verification link sent", preferredStyle: .alert)
let alertActionOkay = UIAlertAction(title: "Okay", style: .default)
let vc = self.storyboard?.instantiateViewController(withIdentifier: "LoginFirstViewController")
self.present(vc!, animated: true, completion: nil)
alertController.addAction(alertActionOkay)
self.present(alertController, animated: true, completion: nil)
}
You directly opened new viewcontroller to prevent this you should add completion handler for uialertaction. When the user press ok button you can open other viewcontroller
let alertController = UIAlertController(title: "Successful!", message: "Email Verification link sent", preferredStyle: .alert)
let alertActionOkay = UIAlertAction(title: "Okay", style: .default) { (action) in
let vc = self.storyboard?.instantiateViewController(withIdentifier: "LoginFirstViewController")
self.present(vc!, animated: true, completion: nil)
}
alertController.addAction(alertActionOkay)
self.present(alertController, animated: true, completion: nil)
I am new to swift, i want to dismiss the alert which is present on
screen when the new alert comes.
I tried:
func showDefaultAlert(controller: UIViewController, title: String, message: String) {
// create the alert
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
// add an action (button)
alert.addAction(UIAlertAction(title: defaultTextForNormalAlertButton, style: UIAlertActionStyle.Default, handler: nil))
// show the alert
//controller.presentViewController(alert, animated: true, completion: nil)
self.showAlert(controller, alert: alert)
}
func showAlert(controller: UIViewController, alert: UIAlertController) {
if let currentPresentedViewController = UIApplication.sharedApplication().keyWindow?.rootViewController?.presentedViewController {
if currentPresentedViewController.isKindOfClass(UIAlertController) {
currentPresentedViewController.dismissViewControllerAnimated(false, completion: {
controller.presentViewController(alert, animated: true, completion: nil)
})
}else {
controller.presentViewController(alert, animated: true, completion: nil)
}
}
}
}
// Call to above method in view controller class:
SPSwiftAlert.sharedObject.showDefaultAlert(self, title:"Title1", message1: "Message")
SPSwiftAlert.sharedObject.showDefaultAlert(self, title:"Title2", message: "Message2")
-
but the above code giving the run time error as :
Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<UIAlertController: 0x7fceb95dcfb0>)
After presenting the UIAlertController you can check its visibility as below:
Presented UIAlertController:
let alerts=UIAlertController(title: "Test", message: "Test", preferredStyle: .Alert)
presentViewController(alerts, animated: true, completion: nil)
Check if the UIAlertController is visible:
if (alerts.isViewLoaded())
{
print("Visible")
//Here you can dismiss the controller
//dismissViewControllerAnimated(true, completion: nil)
}
Check out this demo: Source code
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
#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 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