How to use AlertController in if-else condition statements - ios

I'm creating a function in my Login View controller. Where if the users password or email Address is incorrect he gets an alert saying 'Login not Successful'. But if the users password and email matches he gets to segue to the Dashboard view controller.
func alert(response:String) {
let alert = UIAlertController(title: "Login Failure", message: "Incorrect Email Address, Phone Number or Password", preferredStyle: .alert)
if response == "Login in not sucessful" {
alert.addAction(UIAlertAction(title:"Okay", style: .cancel,handler:nil))
alert.dismiss(animated: true, completion: nil)
self.present(alert, animated: true, completion: nil)
} else if response == "Login Successful" {
self.performSegue(withIdentifier: "dashboardSegue", sender: self)
}
But whenever I tap the Log in button I either get one of these errors:
Warning: Attempt to present <myApp.customTabBar: 0x7fe68a889800> on <myApp.ViewController: 0x7fe68a606f90> while a presentation is in progress!
Warning: Attempt to present <UIAlertController: 0x7fe68b853e00> on myApp.ViewController: 0x7fe68a606f90> while a presentation is in progress!
Warning: Attempt to present <UIAlertController: 0x7fe68b815400> on <myApp.ViewController: 0x7fe68a475240> whose view is not in the window hierarchy!
the alert shows only once and the app segues anyways to the dashboard viewcontroller even though the users email and password are incorrect. I'm thinking maybe its the if-condition statement. I don't whats wrong. I've checked other questions but I can't quite use the viewDidAppear method because I don't want the alert to appear on startup. Newbie Here , Thanks for any help !!!

Change following line of code will fix your issue.
alert.addAction(UIAlertAction(title:"Okay", style: .cancel,handler:nil))
alert.dismiss(animated: true, completion: nil)
self.present(alert, animated: true, completion: nil)
To
alert.addAction(UIAlertAction(title:"Okay", style: .cancel, handler:nil))
self.present(alert, animated: true, completion: nil)

Related

Unable to dismiss a UIAlertController called from a closure

I have a login screen that raises an alert when login fails. The code that calls the alert is run from a callback closure which itself calls a function in the main VC.
_ = UserProfile.logIn(emailAddressLabel.text!, passwordLabel.text!) { success in
if success {
self.performSegue(withIdentifier: "mainTabBarSegue", sender: nil)
}
else {
self.displayFailedLoginAlert()
}
self.loggingIn = false
}
and the displayFailedLoginAlert looks like this:
func displayFailedLoginAlert () {
let alert = UIAlertController(title: "Login", message: "Login Failed", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.default, handler: { _ in
alert.dismiss(animated: false, completion: nil)
}))
self.present(alert, animated: false, completion: nil)
}
However, when I do this I get:
Warning: Attempt to present <UIAlertController: 0x7ff8fd0b5800> on <LoginViewController: 0x7ff8fcc0deb0> which is already presenting <UIAlertController: 0x7ff8fe0cca00>
I have tried a number of different approaches and either get this or a crash if I use a UIAlertController as a class member. What am I doing wrong, I just can't see it?
You don't need to tell the alert to dismiss at all. The default behavior when tapping an action in a UIAlertController is that the alert will dismiss. Just pass nil to the handler.
The issue was that, each time the user logged in I added an observer to the API call. So, on the second login attempt the closure was called twice and so raised the error. Thanks to Frizzo for pointing me in the right direction

Unable to present AlertController from a UIView in Swift

I am trying to display an AlertController in Swift, but not from a UIViewController, but from a UIView that is called from its parent UIViewController. When I try to call the controller, I am getting the following error:
Warning: Attempt to present <UIAlertController: 0x7fa5544a3140> on
<UINavigationController: 0x7fa553830400> whose view is not in the window
hierarchy!
The code that I have which is trying to call the alertController is this:
let logInButton = TWTRLogInButton { (session, error) in
if let unwrappedSession = session {
let alert = UIAlertController(title: "Logged In",
message: "User \(unwrappedSession.userName) has logged in",
preferredStyle: UIAlertControllerStyle.Alert
)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
//self.presentViewController(alert, animated: true, completion: nil)
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
} else {
NSLog("Login error: %#", error!.localizedDescription);
}
}
The commented line in the above block of code is what the original block of code came with, and the line below the comment is the code I tried to replace it with. Can anyone see what it is I'm doing wrong?
Is the root view controller already presenting a view controller? If so, you may need to use:
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentedViewController?.presentViewController(alert, animated: true, completion: nil)
Having said that, it might be easier (and more consistent/appropriate) to use a delegate pattern and let the view tell whatever view controller is managing it to present the alert view controller.
In Swift 5
let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
window?.rootViewController?.presentedViewController?.present(alert, animated: true, completion: nil)
for swift 5 :
UIApplication.shared.keyWindow?.rootViewController?.presentedViewController?.present(alertName, animated: true, completion: nil)

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 can i add a popup that is invoked from my appdelegate class in swift?

I'm working on a google sign in tutorial to my ios app and there's a part when we cannot log in user to my app.
So far the code section in appDelegate.swift looks like:
guard error == nil && data != nil else {
// check for fundamental networking error
print("error=\(error)")
//lets put popup here that says cant connect to server
GIDSignIn.sharedInstance().signOut()
return
}
and now instead of printing the error I want to put the alert popup window. I tried to write there:
let alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
but then I'm getting the xcode error near self.presentViewController saying that value of type AppDelegate has no member presentViewController.
How can I display an alert popup in that case?
In Swift 3
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
Try Using this line :-
self.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
Here you need is a viewController object to present the AlertController, Hope this will help you :)

Parse Log In Error doesn't pop up

I'm developing an iPhone app with Swift using Parse.
I've created a simple log in screen using Parse's PFLoginViewController. There are pop ups (UIAlertControllers) when the user does things like signing up without a username etc, but there is no pop up for when the log in credentials are invalid. Instead I just get an error in the console:
2015-08-23 22:50:10.246 SwifferApp[24429:1614072] [Error]: invalid login parameters (Code: 101, Version: 1.8.1)
I have a function for when the log in fails, but I can't present the UIAlertController over the PFLoginViewController
func logInViewController(logInController: PFLogInViewController, didFailToLogInWithError: NSError?){
var invalidCredentials = UIAlertController(title: "Invalid Credentials", message: "Incorrect username or password.", preferredStyle: UIAlertControllerStyle.Alert)
invalidCredentials.addAction(UIAlertAction(title: "Okay", style: .Default, handler: { (action: UIAlertAction!) in
//do nothing
}))
presentViewController(invalidCredentials, animated: true, completion: nil)
}
On the line with "presentViewController" i get the error
2015-08-23 22:50:10.249 SwifferApp[24429:1613783] Warning: Attempt to present <UIAlertController: 0x7c1f1a50> on <SwifferApp.TimelineTableViewController: 0x7c1b7120> whose view is not in the window hierarchy!
What can I do to include a log in error pop up?
Figured it out!
All I need to do was replace
presentViewController(invalidCredentials, animated: true, completion: nil)
with
logInViewController.presentViewController(invalidCredentials, animated: true, completion: nil)
The error describes the reason itself.
Warning: Attempt to present <UIAlertController: 0x7c1f1a50> on
<SwifferApp.TimelineTableViewController: 0x7c1b7120> whose view is not
in the window hierarchy!
Your TimelineTableViewController is not in view hierarchy. That's why alert is not showing up. If you want to still show the alert not being in the TimelineTableViewController then,
Replace this:
presentViewController(invalidCredentials, animated: true, completion: nil)
With this:
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(invalidCredentials, animated: true, completion: nil)

Resources