This question already has answers here:
How to maintain user session after exiting app in Firebase
(2 answers)
Closed 2 years ago.
I have been looking around for some ways to have my app remember that a user is signed in but could find solutions for Firebase 3. I can login just fine with Firebase authentication but when I quit the app it takes me again to the login. This is closest solution I feel like I have. code snippet
This is what I followed from a youtube tutorial.
Thanks!
You stay logged in with firebase authentication, there's no need to try and re-login users. As long as the user doesn't log out, even if he kills the app, the next time he uses the app, he's automatically logged in. If you want to check if a user is logged in or not, this line of code will get you what you want:
let loggedIn = Auth.auth().currentUser == nil
if loggedIn is true then don't go to login page
If you want to listen to the authentication state of a user, just add an auth state listener after firebase configuration in AppDeledate like so:
FirebaseApp.configure()
Auth.auth().addStateDidChangeListener { (auth, user) in
if let currentUser = user {
// Do something with the current user, for example, fetch user info
// Suppose you have a "users" table in your database and each
// user is distinguished by their 'uid' property, then
Database.database().reference()
.child("users/currentUser.uid")
.observe(.value, with: { snapshot in ... })
}
}
Whenever the auth state changes, this code will be executed
BTW, this auth state listener is very helpful when you want to re-render some screens whenever the auth state changes. You can post a notification in the code above using NotificationCenter.default.post(...), and receive the notifications in your view controllers
Related
Auth.auth().signIn(withEmail:
In my case, When I first time open app and sign in firebase account like above code
then I reopen app
let user = Auth.auth().currentUser
user is not nil and then I reopen app get currentUser again user is nil that mean I did not sign in
I have the other app do like this, but the user always not nil.
I wonder why this happens.
Firebase automatically restores the authenticated user when the app restarts. But this requires a call to the servers, which may take some time. If you check Auth.auth().currentUser while the check is still in progress, you will get nil as the result.
To ensure you get the value once this initial check is done, use an auth state listener as shown in the first snippet in the documentation on getting the current user. From there:
Auth.auth().addStateDidChangeListener { auth, user in
// ...
}
Once this listener fires for the first time:
either the user variable will have a value if the user authentication state could be restored,
or it is nil if the user was not signed in last time the app ran, or the authentication state couldn't be restored (for example, because the account is disabled, or the password was changed).
I think it a big possibility you might be signed in on another device or signed in a different profile and didn't know, you might have some sync problems or security issues that did a safety measurement until you fix the security issue
This question already has answers here:
Why does viewWillAppear not get called when an app comes back from the background?
(7 answers)
Closed 4 years ago.
I am working on project that needs to load the users contacts. For this I need the contacts information. Thus I am using Contacts Framework. It is easy to use and really very fast also. I am new to iOS so I just used the code snippet of getting contacts information.
What I have done: But I have problem, and that is when the user install the application and go the respective ViewController, the ViewController shows Dialog for permission. There user can Deny and Allow the permission. My app works well when user allows the permission but does not work in other way. So I used a function to check if user has given my app the permission or not.
So I read that when user has not granted the permission we can not do anything. Except we can take him to settings where he can allow the permission and get back the app. here is the code I am using to go to the settings app.
if let appSettings = URL(string: UIApplicationOpenSettingsURLString + Bundle.main.bundleIdentifier!) {
if UIApplication.shared.canOpenURL(appSettings) {
UIApplication.shared.open(appSettings)
}
}
Problem:
now my problem is critical, and that is I know I can take user to
settings view, now what if user still do not allow the Permission and
just get back to our App, in this case how to check if user has given
us permission or not??
I am new to iOS and swift so please help me through example. I have searched a lot but did not find anything. In Android there are callback and also onResume could be used, but in iOS I used ViewWillAppear thinking as equivalent of onResume but that did not work.
If you had a refresh button you could do something like the following:
#IBAction func refreshButtonPressed(_ sender: UIButton) {
ContactsService.sharedInstance.CNContactStore.requestAccess(to: .contacts, completion: { granted, error in
if !granted {
//TODO: - Do something (e.g)
self.[method to display an access denied alert to the user]
return
} else {
[insert your code here]
}
}
Also, as another user has stated in a reply to your original question: Why does viewWillAppear not get called when an app comes back from the background? may be of interest to you. You may want to call the contents of the ContactsService.sharedInstance.CNContactStore.requestAccess( .... { } block inside a function and hook that up to a listener for the UIApplication.willEnterForegroundNotification
https://developer.apple.com/documentation/contacts
https://developer.apple.com/documentation/contacts/cncontactstore
https://developer.apple.com/documentation/contacts/cncontactstore/1402873-requestaccess
I created an iOS app with Firebase. So when I launch the app, it ask me to login or register, so that is what I expected. However I would like to "save" the authenticate because when I close and reopen the app I would like to avoid the login page.
Is it possible for an iOS app built with Firebase to "remember" that the user has already log in even before he closed the app?
Take a flag login. when you successfully logged in then make it true.login = true and then update your AppDelegate.swift file i.e. if login true then it will show your desired view.
Firebase automatically persists information about the authenticated user. When the user restarts the app, that information is read and (if possible) its authentication state is restored.
To detect this authentication state you'll need to implement an auth state listener as shown in the documentation on getting the currently signed in user:
handle = Auth.auth().addStateDidChangeListener { (auth, user) in
// ...
}
Finally thanks to Frank van Puffelen I implemented this code :
override func viewDidAppear(_ animated: Bool) {
if Auth.auth().currentUser != nil {
// User is signed in.
performSegue(withIdentifier: "goToHome", sender: self)
} else {
// No user is signed in.
// ...
}
}
Because performSegue() does not perform in viewDidLoad()
In my game I don't want the GameCenter login popup appearing automatically when the app launches. So instead I have a GameCenter button that the user can tap to login with. When they press the button, the login screen appears.
However, it seems like when you launch the app again after logging in, the user still isn't "logged in". They still have to press the button again and then a little banner appears saying "Welcome back, User!". Is there a way to automatically relogin the user without them having to press the button each time? I already entered my credentials, why do I have to authenticate again?
Here is my code, when the user presses the button:
self.authenticatePlayer()
And here's the authenticate method:
func authenticatePlayer() {
let localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {
(view, error) in
if view != nil {
self.view?.window?.rootViewController?.presentViewController(view!, animated: true, completion: nil)
} else {
}
}
}
I need something that can welcome back the user if they already logged in, but NOT ask them to login if they haven't logged in already.
To understand the behavior you're seeing, we need to look at how the authentication process works.
It starts when you set the authentication handler. This is the signal that tells your app to try and talk to Game Center. The authentication handler's completion block has three possible conditions:
Error: something went wrong
Receives a view controller: the login view controller tells you the player isn't logged in
Receives nil view controller: the lack of an error + lack of a view controller tells you the player was already logged in.
Although IOS may be aware of your login state (or attempting to fake your login state using cached info), your app loses that context when you exit. When you startup again, there's been no attempt to set the authentication handler, thus no attempt to verify authentication status until your user presses the button, thus your app doesn't know whether the user is logged in or not.
I think the following approach will get pretty close to what you're looking for:
set the authentication handler and initiate the authentication as early as possible in your first viewController's viewDidLoad. Do this as early as possible in your start up sequence.
If the user isn't authenticated, you will receive a login view controller. Don't present it. Instead, save it. Don't present it unless/until the user presses the button.
If the user is already logged in, they will see the welcome back message as soon as the game starts, and you'll be able to proceed since the user is still logged in.
I understand that by default Firebase invalidates a login token after 24 hours. However, I am finding the behavior strange after this time period. When the app is run it checks to see if the user is logged in and if so it goes into the app otherwise it stays on the login screen:
if self.ref.authData != nil
{
self.performSegueWithIdentifier("mainTabSegue", sender: self)
}
This works fine unless the token has expired after 24 hours. What will happen then is that the app will still see that authData is not nil and it will send it to the next VC. The next VC makes uses of the UID which then causes the app to crash. Running the app again will then show that authData is in fact nil and the user will be asked to login as is expected.
So the question is why, after the 24 hour period, is authData not nil when the user is clearly not logged in? The Firebase documentation seems to indicate that checking authData as above is the correct way to determine whether a user is logged in.
Before your segue if you extract the uid from authData then you can pass that user to the first view controller. If you pass the user object to your first VC constructed in the App Delegate, then your app won't crash. I vaguely remember something similar happening to my app (i.e. where it thinks the user is logged in but then changes back to login). I'm not sure why this happened but it's possible the app tried to start where it left off?
You can also change the token expiration length on Firebase, as you may know.