In my iOS app I made a Login page as the entry point of the app (using storyboard)
However I don't want the user to see the login page each time he uses the app, so I thought of launching the Home page of the app if the user already performed a login in the past.
For that I started to save the login act with NSUserDefaults but I do not know in which of the LoginViewController method I should check for it? Also, is this way to feature "auto logging" a good practice?
Best place is in application:didFinishLaunchingWithOptions
if ([[NSUserDefaults standardUserDefaults] integerForKey:#"UserID"]==0) {
//no user login go back to login page
}
else{
//go in main screen of you application as user already login "root" is storyboard ID of main screen
self.window.rootViewController=[self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"root"];
}
Related
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.
Scenario:
I want to call the logout function if the app is terminated. I'm able to do it using native code:
- (void)applicationWillTerminate:(UIApplication *)app
{
// Run Logout function
}
Problem:
How to do it in IBM mobilefirst hybrid app?
// ************************************************
Edited
First of all, user login in to the app, if the user key in the correct user id and password, it will add the userIdentity into "loginRealm".
WL.Server.setActiveUser("loginRealm", userIdentity);
Next, user closes the apps without logout. So, when the user login for the another time, MFP server will not return any feedback since it will hit this exception:
Cannot change identity of an already logged in user in realm
'loginRealm'. The application must logout first.
Hence, I have to logout the user from MFP server by setting the "loginRealm" to null in adapter;
WL.Server.setActiveUser("loginRealm", null);
The above line of code is in the logout function defined in authentication-config.xml.
The client side device runs this line of code and it will trigger the logout function. Besides, it will reload the App upon success:
WL.Client.logout('loginRealm', {
onSuccess: WL.Client.reloadApp
});
Steps that I've tried:
1) At WlcommonInit() I added WL.Client.updateUserInfo(); and if WL.Client.isUserAuthenticated("loginRealm") return true I will logout the user from server. However, WL.Client.isUserAuthenticated("loginRealm") will always return false. This is because, it needs to take sometime around (30seconds to 2 minutes) for the flag to turn true after WL.Client.updateUserInfo();. So my login still fail and hit the same error.
2) I tried to logout the users during the user click login button. But the app will refresh and return to login page again due to reloadApp. The logout code I get from IBM mobilefirst website. So user need to click and type 2 times in order to login into the main menu.
WL.Client.logout('loginRealm', {
onSuccess: WL.Client.reloadApp
});
Am I doing it wrongly? Or are there any other methods to get WL.Client.isUserAuthenticated("loginRealm") return true instantly after WL.Client.updateUserInfo(); ? Can we remove the reload app line of code in logout function?
I don't think this is doable, because that logout function (in MFP) will require server connectivity (request and response) and if the app is by then killed, I think it's going to cause unpredictable results.
Note though that it seems to be not recommended to use that function anyway? applicationWillTerminate when is it called and when not
What you should do perhaps in order to simulate it, is to logout-on-login, so that it would appear that the app is logged out when opening it. You can extend the duration of the splash screen so that the end-user will not see that s/he is logged in (in case the session was still alive between the closing and re-opening of the app), until really logged out and then you can display the login screen again or any other required screen.
I have the following problem, I would like to know if there is something implemented by facebook or if you know a workflow to avoid this issue.
Basically I use facebook SDK to login, the app send me to the browser, and instead of clicking cancel or Accept/OK, I click home button and get back to the app.
In that case I don't receive any callback from facebook SDK.
Also, facebook have a delay when you click cancel or ok button, so when you get back to the app you don't know exactly if you are going to receive the callback or not by 2-3 seconds aprox.
My current solution is giving a delay of 3-4 seconds and check if you are already connected or not, and show the buttons again if you are not connected. It's a really bad approach, but I can't find something better for that.
You're supposed to handle this in your AppDelegate's applicationDidBecomeActive method:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Handles activation with regards to returning from iOS 6.0 authorization dialog or from fast app switching
[FBSession.activeSession handleDidBecomeActive];
}
Docs here: https://developers.facebook.com/docs/reference/ios/current/class/FBSession/#handleDidBecomeActive
and
https://developers.facebook.com/docs/ios/ios-sdk-tutorial/authenticate/
I have an app in which the user may choose to login to FB. My code is based largely on the tutorials at FB, and for the most part, the app, and the FB integration works as expected. The problem I am having is that the app is not remembering from launch to launch that the user has selected to connect the app to FB. I put a check into AppDelegate.m to check for a cached FBSession:
if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) {
// Yes, so just open the session (this won't display any UX).
NSLog(#"The state is IS 'State created token loaded'");
[self openSessionWithAllowLoginUI:NO];
} else {
// No, display the login page.
NSLog(#"The state is NOT 'State created token loaded'");
[self openSessionWithAllowLoginUI:YES];
}
Every time I launch the app, the line "The state is NOT 'State created token loaded'" is displayed in the console. This makes me think I am not doing something right in order to make that FB login persist from launch to launch.
I could really use some advice here. What does one need to do to ensure that "FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded" is true on app launch?
If you have this code right when the app starts, then note that:
FBSession.activeSession
May not be set yet. What you want to do to check for a cached token is something like:
if (![self openSessionWithAllowLoginUI:NO]) {
[self openSessionWithAllowLoginUI:YES];
}
The first call with the "NO" will return synchronously with a value of true if there was a a cached token. It returns no if there is no cached token. At this point you can force the login UX to happen.
As the title says, my project will never bring up the FB login screen until I have called
[facebook logout];
This makes sense when I've already logged in, but it happens on startup as well (i.e. the user is not yet logged in).
Hmmm...I've just tried resetting contents and settings in the simulator, and that seems to have fixed the problem. For my own peace of mind, why when I close the simulator and rerun the project does it not revert to either a state where the app is 'new' and hasn't been run before, or to a resume state - whereby the logged in user info would be available immediately?
On my device I have just tested this:
Fresh install
Open app, login via FB Connect
Close app, remove from running in background apps
Reopen app
Try to login, no response until I first click logout
So is it somehow retaining the fact that it has logged in before? If so, is there a "loggedInAlready" variable or something similar that I can check against?
Added this to didFinishLaunchingWithOptions
if([facebook isSessionValid])//if already able to log in
{
[self loginToFacebook];//attempt to login automatically on startup
}
Seems to have solved the problem. I guess that because I had:
if([facebook isSessionValid]){
[facebook login];
}
in the login button press, that when it resumed it was still in a valid session and so the button press wouldn't do anything until the logout button ended the session.
Now it automatically checks if the session is valid on startup, and if so it logs straight in for me.
:-) All's well that ends well.