I'm new to swift and Xcode. I creating a user registration view controller and I'm using Firebase as my DB. Here is what I've written:
#IBAction func registerButton(_ sender: Any) {
//Register user functions
Auth.auth().createUser(withEmail: emailField.text! , password: passwordField.text!) { (user, error) in
if error != nil {
print (error!)
} else {
//success
print ("Registration successful")
self.performSegue(withIdentifier: "registerToList", sender: self)
}
}
}
When a user inputs data that is incorrectly formatted, such as blank fields or improperly formatted email, my console prints out the error. However, the user is still able to bypass the registration view controller and move on to the next screen. Why is that?
I also want to note that I'm using a Show segue - is this the issue? I can't use a push segue since it has been deprecated.
Related
Here is the code:
#IBAction func loginTapped(_ sender: Any) {
let email = emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
if error != nil {
self.errorLabel.text = error!.localizedDescription
self.errorLabel.alpha = 1
print(error!.localizedDescription)
}
else {
self.performSegue(withIdentifier: "loginSegue", sender: nil)
print("User is signed in with Firebase.")
}
}
}
I have a segue, loginSegue, connected from the login button to the homeViewController. Within in the if error statement I would like to stop the segue from going through because the user has not signed in. The goal here is not allow the user to go forward if they get an error. Is there an "opposite" to the performSegue(withIdentifier: String, sender: Any?) ?
First , there is no "opposite" to performSegue(withIdentifier: String, sender: Any?).
But the issue is not about this. I think you wired the segue from the login button and gave it an identifier. If you wire a segue from a button directly the button is always going to execute that segue. Doing some operations in the button's action does not effect.
You need to wire a segue from FirstVc to SecondVc (not from the button) and then give the segue an identifier. Then, from the button's action you can check if there is no error and call performSegue(withIdentifier: String, sender:) passing your segue's identifier.
I think your button is connected to perform segue in storyboard. So your button has two actions - one from storyboard to perform segue and second in your code. Just remove the connection from storyboard and connect only UIViewControllers not with your button.
You could override the shouldPerformSegue(withIdentifier:,sender:) method and return false if the login fails and you don't want to perform the segue. Here's an example
override func shouldPerformSegue(withIdentifier identifier: String?, sender: Any?) -> Bool {
if let ident = identifier {
if ident == "YourIdentifier" {
if loginSuccess != true {
return false
}
}
}
return true
}
The current view controller gets dismissed as soon as I call the signOut method by pressing the button. The signing out process however is successful. (I'm using the FirebaseAuth SDK.)
Here is my code:
#IBAction func logoutPressed(_ sender: Any) {
do {
try Auth.auth().signOut()
} catch let signOutError as NSError {
showAlertSaying(
title: "Fehler beim ausloggen",
message: "Ein Fehler ist aufgetreten",
view: self
)
print ("Error signing out: %#", signOutError)
}
}
Is there any way to prevent that the view controller gets dismissed?
It appears that your storyboard button is linked to another action in addition to this
#IBAction func logoutPressed(_ sender: Any) {
which has a dismiss / pop action
This scenario happens when you copy elements in storyboard
So when the user first opens my app they will see a view with a button to proceed with logging in or registering. In my Login view, I have a button handler (attached via action) which is called when a user presses a login button. Despite me using UserDefaults to store logged in state, my app does not go straight to my Dashboard view automatically. Any ideas why?
// Firebase auth in doLogin action (Login VC)
Auth.auth().signIn(withEmail: un, password: pw)
{
(resp, err) in if (err == nil && resp != nil)
{
if (resp!.user.isEmailVerified)
{
// segue from Login VC to Dashboard VC will be exectuted
self.performSegue(withIdentifier: "loggedin", sender: nil)
// store the logged in state as true for the future
UserDefaults.standard.set(true, forKey: "loggedin")
UserDefaults.standard.synchronize()
}
}
}
Here is the code for the Main view controller to determine if it should proceed directly to dashboard.
func loggedIn() -> Bool {
// determine if the user is still logged into the app
return UserDefaults.standard.bool(forKey: "loggedin")
}
override func viewDidLoad() {
super.viewDidLoad()
if (loggedIn())
{
// logged in, return to the dashboard view controller
performSegue(withIdentifier: "persisted", sender: nil)
}
}
I've tried using print statements and either the loggedIn function isn't being executed for whatever reason or the console is just too flooded with Firebase debug log statements to even see these.
You have to embed your main view controller inside a UINavigationController to make the persisted segue work.
I'm having a problem where every time I enter the right credentials, it brings me to one view controller then opens up the same view controller again even though I only have the login viewer controller linked to one view controller. If I don't enter the right credentials it still brings me into the linked view controller. Here is the code.
EDIT: Using a push segue(show)
#IBAction func loginTapped(_ sender: Any) {
if let Email = userEmail.text, let Pass = userPassword.text{
Auth.auth().signIn(withEmail: Email, password: Pass, completion: { (user, error) in
if error != nil{
print("incorrect")
}
else{
if error == nil{
self.performSegue(withIdentifier: "loginPage", sender: self)
print("correct")
}
}
})
}
}
I don't know if you've fixed your problem, but check your storyboard. Sounds like you have a segue connected from the button to the next ViewController which would result in pressing the button and it'll always push that ViewController.
To do this easily just see if you have a segue connected from the button to your destination ViewController in your MainStoryboard.
I have a login view controller where it should prevent the user from transition to the next view controller via a segue called "toMasterTab". I think the logic might be wrong - if the user entered the correct credentials and is not empty, it transitions fine, but if the user entered no credentials (nil) and entered the wrong credentials, then it should prevent the segue. So far, I can only get the UIAlertView to pop up, but other than that, I can't solve this...
#IBAction func loginButton(sender: AnyObject) {
let RedPlanetUser = RPUsername.text
let RedPlanetUserPassword = RPUserPassword.text
PFUser.logInWithUsernameInBackground(RedPlanetUser!, password: RedPlanetUserPassword!) {
(user: PFUser?, error: NSError?) -> Void in
if user != nil {
// Do stuff after successful login
self.performSegueWithIdentifier("toMasterTab", sender: self)
print("User logged in successfully")
} else {
// Login failed
print("User log in failed")
// Present alert
var alert = UIAlertView(title: "Login Failed",
message: "The username and password do not match.",
delegate: self,
cancelButtonTitle: "Try Again")
alert.show()
func shouldPerformSegueWithIdentifier(identifier: String!, object: AnyObject) -> Bool {
let identifier = "toMasterTab"
// prevent segue
return false
}
}
}
}
I believe you should be overriding the
override func shouldPerformSegueWithIdentifier
The problem was that the segue was connected to the button, so it automatically performed the segue even when the conditions were NOT met. I connected the segue from VC1 to VC2 and used the following code when the conditions were met, and didn't call the segue when the conditions were erroneous:
self.performSegueWithIdentifier("toMasterTab", sender: self)