How do I close a view after firebase google sign in - swift

I have the code working for a swift 4 firebase google log in. The problem is after sign in, it just drops me back onto the view that was used for the sign in. Where do I execute the code to automatically close the view after the sign in?

I am assuming that your code looks something like this.
FIRAuth.auth()?.signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!) { (user, error) in
if error == nil {
//Print into the console if successfully logged in
print("You have successfully logged in")
//Go to the HomeViewController if the login is sucessful
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.present(vc!, animated: true, completion: nil)
//If you want to go back to the previous view then call
//For view embedded in navigation controller use,
self.navigationController?.popViewController(animated: true)
//For view that was presented use,
self.dismiss(animated: true, completion: nil)
} else {
//Tells the user that there is an error and then gets firebase to tell them the error
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}

Related

AWS Cognito doesn't call confirmSignUp when confirming user identity in Swift with Xcode

I finally managed to get the SignUp to work, but when trying to confirm the signup, I'm reaching a problem. Here is my code:
var user: AWSCognitoIdentityUser?
#IBAction func submitButton(_ sender: Any) {
guard let confirmationCodeValue = self.codeTextField.text, !confirmationCodeValue.isEmpty else {
let confirmationAlert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
confirmationAlert.addAction(UIAlertAction(title: "好", style: .default, handler: {action in
print("Try again!")
}))
self.present(confirmationAlert, animated: true, completion: nil)
return
}
self.user?.confirmSignUp(self.codeTextField.text!, forceAliasCreation: true).continue({[weak self] (task: AWSTask) -> Any? in
guard let strongSelf = self else { return nil }
DispatchQueue.main.async(execute: {
print("At least this is working...")
if let error = task.error {
let confirmationFailAlert = UIAlertController(title: (error as NSError).userInfo["__type"] as? String,
message: (error as NSError).userInfo["__type"] as? String,
preferredStyle: .alert)
confirmationFailAlert.addAction(UIAlertAction(title: "好",
style: .default,
handler: {action in
}))
self?.present(confirmationFailAlert, animated: true, completion: nil)
} else {
let confirmationSuccessAlert = UIAlertController(title: self?.alertTitleConfirmationComplete,
message:self?.alertMessageConfirmationComplete,
preferredStyle: .alert)
confirmationSuccessAlert.addAction(UIAlertAction(title: "好",
style: .default,
handler: {action in
self?.dismiss(animated: true, completion: nil)
}))
self?.present(confirmationSuccessAlert, animated: true, completion: nil)
}
})
return nil
})
}
The first part of this code works fine. If I type nothing in the space, I get an alertView telling me so. However, if I type anything in the space, nothing happens. The print statement "At least this is working..." never gets called. I've been staring at this code for a couple hours now trying to figure out what's wrong, and I feel like it's probably something simple, but as of now, I could use some help!
Thanks in advance!
I assume the code block above is not the full source, but be sure the optional, user, is "unencapsulated" and equal to an actual instance of AWSCognitoIdentityUser.
If it isn't, which I am assuming it is not, confirmSignUp won't know the username, sub, or have any information on the user it is "confirming".
I would recommend logging user and be sure that username is in fact a value within user.
I believe you set it equal to that instance type in the response to your AWSCognitoIdentityUserPool class signUp:password:userAttributes:validationData: call.
Check those values that are returned in AWSCognitoIdentityUserPoolSignUpResponse.

ViewController segue and login

I'm new to Swift (and programming in general). I'm having some difficulties in Xcode with the login feature. What I want is that the user should be logged in if no errors was returned and the user should be sent to another controller. I've read some of the documentation from Apple and the performSegueWithIdentifier (and of course some questions asked here), but it still does not work when I use a segue with push or modal that are given an identifier. Either the app crashes, or the user is sent to my UITabBarController even if the credentials was incorrect.
This is my LogInViewController.swift:
#IBAction func loginAction(sender: AnyObject)
{
if self.emailField.text == "" || self.passwordField.text == ""
{
let alertController = UIAlertController(title: "Oops!", message: "Please enter an email and password.", preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alertController.addAction(defaultAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
else
{
FIRAuth.auth()?.signInWithEmail(self.emailField.text!, password: self.passwordField.text!) { (user, error) in
if error == nil
{
self.emailField.text = ""
self.passwordField.text = ""
}
else
{
let alertController = UIAlertController(title: "Oops!", message: error?.localizedDescription, preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alertController.addAction(defaultAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
// User Logged in
self.performSegueWithIdentifier("LoggedIn", sender: self)
}
}
}
The error I get in the console:
2016-09-04 14:55:30.019 DrinkApp[37777:1006336] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'LoggedIn'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
There are two main ways to send a user to another View Controller. The first is performSegueWithIdentifier. Here's how you would go about using that:
First of all, control-drag from the yellow circle of the original VC to the target VC in the interface builder.
Next, click on the 'segue arrow' that appears between the two View Controllers.
In the identifier field, type in mySegue.
Next, go back to your code. When you reach the sign in section, add the following code:
self.performSegueWithIdentifier("mySegue", sender: nil)
The second method is a bit more advanced. Here's how that would work:
First, click on the yellow circle of the destination VC. Click on the newspaper, then call the storyboard ID myVC.
Make sure to click on Storyboard ID
Go back to the same part of the code and copy and paste this code:
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initViewController: UIViewController = storyboard.instantiateViewControllerWithIdentifier("myVC") as UIViewController
self.presentViewController(initViewController, animated: true, completion: nil)
Comment down below if you have any questions. Good luck!
Here is a Firebase login example:
func login() {
FIRAuth.auth()?.signInWithEmail(textFieldLoginEmail.text!, password: textFieldLoginPassword.text!) { (user, error) in
if error != nil {
let alert = UIAlertController(title: "User Authentication error",
message: error?.localizedDescription,
preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "OK",
style: .Default) { (action: UIAlertAction!) -> Void in
}
let resetPasswordAction = UIAlertAction(title: "OK",
style: .Default) { (action: UIAlertAction!) -> Void in
}
alert.addAction(OKAction)
guard let errorCode = FIRAuthErrorCode(rawValue: (error?.code)!) else { return }
switch errorCode {
case .ErrorCodeWrongPassword:
alert.addAction(resetPasswordAction)
case .ErrorCodeNetworkError:
print("Network error")
default:
print("Other error\n")
break
}
self.presentViewController(alert, animated: true, completion: nil)
} else { // User Logged in
self.performSegueWithIdentifier("MySegue", sender: self)
}
}
}
I only handled two errors for this example.
If you use push segue, you need to have navigation controller, and your root segue should lead to the login view controller, then another segue to the next view controller. This last segue must have an identifier (in this case it's MySegue)
Edit:
Since it seems that your problem is not with Firebase, but with setting up the storyboard. Here is an example:
Set up one UINavigationController two UIViewControllers
Control Drag between the UINavigationController to the middle UIViewControllers and choose root view controller from the popup menu
Control Drag between the UIViewController to the last UIViewControllers and choose show
select the segue added in the previous step and change its identifier (in the attributes inspector) to MySegue.
5.Choose the Middle UIViewControllers and change the class name (in the identity inspector) to your login view controller class.
Here is the full setup:
control drag menu (step 2):
Segue attributes inspector (step 4):
I found this answer mentioned here to be super elegant.
https://fluffy.es/how-to-transition-from-login-screen-to-tab-bar-controller/
it works with tab bars, and nav bars. you create a function in the scene delegate, that switches the root view controller. you access the scene delgates functions and windows with (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?

How to add Admob Interstitial before Segue?

I'v been trying to deal with this problem for a good while but cant figure out how to fix it.
Currently I'v added Admob to my project and the interstitial's are displaying but when I exit the interstitial it returns me to my previous VC (where the interstitial instance is made).
As you can see below im trying to add them to my Tabbar functions. But the segue never happens nor do the alerts show before the interstitial. I wanted to show the the ad then segue to the VC. And I want the user to see the alert and press "OK" before seeing the interstitial.
Any help would be awesome!
//TabBar Functions
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
if (item.tag == 1) {
if (self.interstitial.isReady) {
self.interstitial.presentFromRootViewController(self)
}
self.performSegueWithIdentifier("showStore", sender: nil)
} else if (item.tag == 2) {
let alert = UIAlertController(title: "Coming Soon!", message: "Loadout", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Got It!", style: .Default, handler: nil))
if (self.interstitial.isReady) {
self.interstitial.presentFromRootViewController(self)
}
self.presentViewController(alert, animated: true, completion: nil)
return
} else if (item.tag == 3) {
let alert = UIAlertController(title: "Coming Soon!", message: "God's Tower", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "Got It!", style: .Default, handler: nil))
if (self.interstitial.isReady) {
self.interstitial.presentFromRootViewController(self)
}
self.presentViewController(alert, animated: true, completion: nil)
return
}
}
Set your GADInterstitial's delegate and then segue once the ad has been dismissed.
// Add this where you're creating your GADInterstitial
interstitial.delegate = self
func interstitialDidDismissScreen(ad: GADInterstitial!) {
// Segue to your view controller here
}
For a complete list of ad events refer to GADInterstitialDelegate implementation.

Open a new view controller after login alert swift 2.0

I am trying to change view controller if the login is successful but I am unsure how to do this. This is what i have tried so far. Thanks in advance!
#IBAction func signinaction(sender: AnyObject) {
let user = self.usernamefield.text!
ref.authUser(emailfield.text, password: passwordfield.text, withCompletionBlock: { error, authData in
if error != nil
{
let alert = UIAlertController(title: "Error", message: "Enter Email and Password.", preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: .Default, handler: nil)
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
print("can not sign in")
}
else
{
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewName:NSString = "NewView"
let vc = storyboard.instantiateViewControllerWithIdentifier(viewName as String) as! HomeViewController
let uid = authData.uid
print("Success with user: \(uid)")
let alert = UIAlertController(title: "Success", message: "Welcome \(user)", preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: .Default, handler: nil)
alert.addAction(action)
self.navigationController?.pushViewController(vc as HomeViewController, animated: true)
}
})
}
Assuming that the view controller all of this is in is contained in a navigation controller, what you have should be working fine. Note, however that you're creating an alert you never show. My guess is that you want to display the success alert and then open the new view controller, something like:
let alert = UIAlertController(title: "Success", message: "Welcome \(user)", preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: .Default) { _ in
self.navigationController?.pushViewController(vc, animated: true)
}
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
If this still isn't working, I'd make sure the current view controller is actually displayed in a navigation controller.
Looks like you just need to add the navigation code inside of the alert action. Currently you have the handler parameter set to nil
this
let action = UIAlertAction(title: "Ok", style: .Default, handler: nil)
becomes this
let alertAction = UIAlertAction(title: "Ok", style: .Default) { (action) -> Void in
self.navigationController?.pushViewController(vc as HomeViewController, animated: true)
}

Show alert view when tap on phone number in web view with Swift

I'm having a web view that displays a company's address and phone number and email. The current behavior is when the phone number is tapped it is then dialled immediately.
Is there a way for me to prompt an alert view to let user confirm the call? Instead of calling it immediately?
Here is the function I use to initialize an alert:
func displayAlert(title: String, message: String) {
var 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)
alert.hidesBottomBarWhenPushed = true
}))
print("running Activityindicator code")
self.presentViewController(alert, animated: true, completion: nil)
}
and I call it like so:
self.displayAlert("Alert title", message: "alert message")
hope this helps!