iOS Firebase - how to check if user not logged in - ios

I wan't to check if the user is't logged into my app.
If that happend, i wan't to redirect him to notLoggedView or verifyAccuontView.
At this moment code looks like this and if user not created i can't get into notLoggedView.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true);
let user = Auth.auth().currentUser;
if (user == nil) {
self.performSegue(withIdentifier: "notLoggedView", sender: self);
}
}
This code works same as above (like user exist, but firebase accounts is empty)
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true);
if let user = Auth.auth().currentUser {
// action when account exist
} else {
self.performSegue(withIdentifier: "notLoggedView", sender: self);
}
}

override func viewDidLoad() {
super.viewDidLoad()
Auth.auth()!.addStateDidChangeListener() { auth, user in
if user != nil {
self.switchStoryboard()
}
}
}
or You can check directly
if Auth.auth().currentUser?.uid != nil {
//user is logged in
}else{
//user is not logged in
}
for Signup you use
Auth.auth().createUser(withEmail: emailField.text!, password: passwordField.text!) { user, error in
if error == nil {
// 3
Auth.auth().signIn(withEmail: self.textFieldLoginEmail.text!,
password: self.textFieldLoginPassword.text!)
}
}

If you want to check if there is no user logged in, check currentUser directly.
let user = Auth.auth().currentUser;
if (user == nil) {
// there is no user signed in when user is nil
}
Also be sure see the documentation for more information.

Related

Swift Firebase: how to check user is verified after send email?

After creating account i sending an email with verification link:
func sendVerificationMail() {
if self.authUser != nil && !self.authUser!.isEmailVerified {
self.authUser!.sendEmailVerification(completion: { (error) in
// TODO Notify user email was sent or not because of error
})
} else {
// TODO Notify everything is OK
}
}
And in other place i checking it confirmed:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if Auth.auth().currentUser != nil && Auth.auth().currentUser!.isEmailVerified {
self.performSegue(withIdentifier: "toMainScreen", sender: self)
} else {
self.performSegue(withIdentifier: "notLoggedView", sender: self)
}
}
Even if confirmed, i always go to notLoggedView. Somebody can explain why?
I have faced the similar issue and to solve it I have to reload the profile. Try this.
func loginUser() {
Auth.auth().currentUser?.reload(completion: { (error) in
if let error = error {
print(error)
} else {
if Auth.auth().currentUser != nil && Auth.auth().currentUser!.isEmailVerified {
self.performSegue(withIdentifier: "toMainScreen", sender: self)
} else {
self.performSegue(withIdentifier: "notLoggedView", sender: self).
}
}
})
}
Also, instead of writing Auth.auth().currentUser every time you can store that in a variable. And, you can use this function wherever you want.
if let authUser = Auth.auth().currentUser { //You can also get current user like this in a safe way
//Do your stuff here
}

Firebase Anonymous Auth, Nil User

I'm using Firebase database and offer anonymous login. The first anonymous login made on a single device works as expected. If I sign out and attempt any more anonymous logins, it succeeds, the completion block has no error and returns a user.
However, once it's all done and we're out of the completion block, Auth.auth().currentUser() is nil.
If I run a simple Timer checking Auth.auth().currentUser() every second, throughout the entire login process it is always nil and never changes.
Quick breakdown of code:
Login anonymously.
Check if id exists in db.
Update profile displayName with id for easy referral later.
Fetch client in db.
All go wrong!
Tap a button to sign in.
#IBAction func clientLoginBtnTap(_ sender : UIButton) {
self.clientActivityIndicator?.showActivityIndicator()
Auth.auth().signInAnonymously { (user, error) in
if error == nil {
//check id matches available client
self.checkClient(id: (self.clientIdField?.text)!, completion: { (isValid) in
if isValid == true {
//now signed in, update client id
let profileChangeRequest = user?.createProfileChangeRequest()
profileChangeRequest?.displayName = self.clientIdField?.text
profileChangeRequest?.commitChanges(completion: { (error) in
if error == nil {
//done
UserDefaults.standard.set(true, forKey: kIS_USER_CLIENT_NOT_TRAINER)
self.dismiss(animated: true, completion: {
//self.delegate?.didLoginAsClient()
})
}
else {
self.logout()
self.clientIdField?.shake()
self.clientActivityIndicator?.hideActivityIndicator()
}
})
}
else {
self.logout()
self.clientIdField?.shake()
self.clientActivityIndicator?.hideActivityIndicator()
}
})
}
else {
}
}
}
func checkClient(id : String, completion: #escaping (_ isValid : Bool) -> Void) {
let ref = Database.database().reference().child("v2").child("clients").child(id)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() { completion(true) }
else { completion(false) }
}) { (error) in
completion(false)
}
}
func logout() {
do {
try Auth.auth().signOut()
}
catch let error as NSError {
print (error.localizedDescription)
}
}
Login is successful.
Then this runs after login and the user exists but Auth.auth().currentUser() is nil. When a client login happens, I try to get the client data but permission is denied because we have no user.
handle = Auth.auth().addStateDidChangeListener { (auth, user) in
self.currentUser = user
if user == nil {
self.updateForNoUser()
}
else {
self.updateForUser()
}
}
func updateForUser() {
//Trainer Logged in
if UserDefaults.standard.bool(forKey: kIS_USER_CLIENT_NOT_TRAINER) == false {
self.performSegue(withIdentifier: "master", sender: self)
}
//Client Logged in
else {
if let id = Auth.auth().currentUser?.displayName {
let ref = Database.database().reference().child("v2").child("clients").child(id)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
self.client = Client(snapshot: snapshot)
self.performSegue(withIdentifier: "masterClient", sender: self)
}
}) { (error) in }
}
else {
do {
try Auth.auth().signOut()
}
catch let error as NSError {
print (error.localizedDescription)
}
}
}
}

Firebase automatic login on iOS

Is there a better way to make a user automatically login to the app as long as they have logged in in the past; other than saving their login details directly to the storage which may be insecure?
Thanks
PS: I'm using Firebase and Swift for iOS
EDIT: Here's the code
import UIKit
import Firebase
class loginVC: UIViewController {
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidAppear(animated: Bool) {
automaticLogin()
}
#IBAction func loginTapped(sender: AnyObject) {
errorLabel.text = ""
FIRAuth.auth()?.createUserWithEmail(emailTextField.text!, password: passwordTextField.text!, completion: {
user, error in
if error != nil {
FIRAuth.auth()?.signInWithEmail(self.emailTextField.text!, password: self.passwordTextField.text!, completion: { (user, error) in
if error == nil {
self.login()
} else if error != nil {
self.errorLabel.text = ("Invalid email address or password")
print(error)
}
})
} else {
print("user created")
self.login()
print(user?.displayName)
}
})
}
#IBAction func forgotPasswordTapped(sender: AnyObject) {
let email = emailTextField.text
errorLabel.text = ""
FIRAuth.auth()?.sendPasswordResetWithEmail(email!) { error in
if error != nil {
self.errorLabel.text = ("Invalid email address")
print(error)
} else {
self.errorLabel.text = ("Password reset email successfully sent")
print("password reset email sent")
}
}
}
func login() {
FIRAuth.auth()?.signInWithEmail(emailTextField.text!, password: passwordTextField.text!, completion: {
user, error in
if error != nil {
self.errorLabel.text = ("Invalid email address or password")
print(error)
} else {
print("login successful")
self.checkIfUserIsNew()
}
})
}
func checkIfUserIsNew() {
if FIRAuth.auth()?.currentUser?.displayName != nil || FIRAuth.auth()?.currentUser?.displayName == "" {
self.performSegueWithIdentifier("showChatVC", sender: self)
} else {
self.performSegueWithIdentifier("showOptionsVC", sender: self)
}
}
func automaticLogin() {
FIRAuth.auth()?.addAuthStateDidChangeListener { auth, user in
if user == user {
print("still signed in")
} else {
print("not signed in")
}
}
}
I also used this to logout the user:
#IBAction func logOutTapped(sender: AnyObject) {
try! FIRAuth.auth()?.signOut()
performSegueWithIdentifier("showLoginVC", sender: self)
print(FIRAuth.auth()?.currentUser?.displayName)
}
You might want to use NSUserDefaults. To do this in your login() function you might want to save your user's data once they signed in or create an account. Inside your login function you can start by creating new variable to grab your user's email / password.
let userDefaults = UserDefaults.standard
userDefaults.setValue(self.emailField.text!, forKey: "email")
userDefaults.setValue(self.passField.text!, forKey: "password")
Next, you also need to implement a new function called viewWillAppear, which will be called before the view controller. And you might also put some arguments inside your login function.
override func viewWillAppear(_ animated: Bool) {
let userDefaults = UserDefaults.standard
if userDefaults.string(forKey: "email") != nil {
let email = userDefaults.string(forKey: "email")
let password = userDefaults.string(forKey: "password")
login(email: email!, password: password!)
}
}
the if statement will check wether your user already registered their email account or not yet. Lastly you need to update your login function to have two parameters, to pass in the email and password of the user.

performSegueWithIdentifier outside of viewDidAppear not working

I am sure this is a beginners question, but I am trying to perform a Segue if the users of my application are logged into Facebook, or if they do in the initial screen. In the viewDidAppear function, I test if they are already logged in, and if they are, the segue works just fine. But in my other function, is does absolutely nothing (not even an error).
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (PFUser.currentUser() == nil) {
//...//
} else {
print("User already logged in")
self.performSegueWithIdentifier("mainMenuSegue", sender: self) // This one is Working
}}
func logInViewController(logInController: PFLogInViewController, didLogInUser user: PFUser) -> Void {
print("We just logged you in!")
if PFUser.currentUser()!["First_Name"] == nil {
returnUserData() } else {
print(NSThread.isMainThread()) //Returning True
self.performSegueWithIdentifier("mainMenuSegue", sender: self)// This one is NOT Working
}
}
What am I doing wrong?
In iOS 6 and later it´s possible: You have to implement the method in the controller and return true or false
if you return false segue will fail to goto destination.
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
in swift
override func shouldPerformSegueWithIdentifier(identifier: String!, sender: AnyObject!) -> Bool {
//todo
}

Swift - Dismissing Alert Message Closes View Controller

I have a registration process where I have an entry point with a Login/register with Facebook (Connected to Parse). If the user has never registered with their Facebook account, then they are sent to a send page where a user registers a username, email and password. I have a function setup that if a user leaves any of the text fields blank for the user registration, then a alert message appears with an error stating the field is blank. This functionality works correctly, but when I click "OK" to dismiss the message, the registration view controller dismisses itself and the entry point (login screen) view controller is displayed. This should not be happening and I don't have a segue setup to go from registration screen to login screen. Any thoughts?
One thing that pops out to me is the error in the console log, which I believe is actually associated with the Parse if/else statement, and not with the field == nil statement.
Console Log:
2015-04-14 10:42:56.293 tappery[574:142525] [Error]: missing username (Code: 200, Version: 1.6.3)
Login Screen View Controller:
import UIKit
class LoginViewController: UIViewController {
#IBOutlet var loginCancelledLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var currentUser = PFUser.currentUser()
if currentUser != nil {
println("User is Logged in")
} else {
println("User is not logged in")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func facebookLoginButton(sender: AnyObject) {
var permissions = ["public_profile", "email", "user_friends"]
self.loginCancelledLabel.alpha = 0
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if let user = user {
if user.isNew {
println("User signed up and logged in through Facebook!")
self.performSegueWithIdentifier("registerUser", sender: self)
} else {
println("User logged in through Facebook!")
self.performSegueWithIdentifier("loginSuccessful", sender: self)
}
} else {
println("Uh oh. The user cancelled the Facebook login.")
self.loginCancelledLabel.alpha = 1
}
})
}
}
Registration View Controller:
import UIKit
class UserRegistrationViewController: UIViewController {
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)
}
#IBOutlet var usernameTextField: UITextField!
#IBOutlet var emailTextField: UITextField!
#IBOutlet var passwordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func registerUser(sender: AnyObject) {
var error = ""
if usernameTextField.text == nil || emailTextField.text == nil || passwordTextField.text == nil {
error = "Please enter a username, email and password"
}
if error != "" {
displayAlert("Error In Form", error: error)
} else {
var user = PFUser.currentUser()
user.username = usernameTextField.text
user.password = passwordTextField.text
user.email = emailTextField.text
user.saveInBackgroundWithBlock {
(succeeded: Bool!, signupError: NSError!) -> Void in
if signupError == nil {
println(user.username)
println(user.password)
println(user.email)
self.performSegueWithIdentifier("successfulRegistration", sender: self)
// Hooray! Let them use the app now.
} else {
if let errorString = signupError.userInfo?["error"] as? NSString {
error = errorString
} else {
error = "Please try again later."
}
self.displayAlert("Could Not Sign Up", error: error)
}
}
}
}
Remove self.dismissViewControllerAnimated(true, completion: nil) from your OK button UIAlertAction's handler. Alert is dismissed automatically upon OK button click and you're dismissing registration controller with this call.

Resources