4

The below code is working but has a bug. The scenario is that, I begin by logging in to enter the app system. Once the login has succeeded, the app will set UserDefaults (UserId). After that, I can navigate the app views with stored UserId. Once I go to settings and tab logout, that will clean UserId and go to login view.

The BUG: When I login again to the app and click the home button to go to iPhone desktop and close the app, and return to open it again it still storing the UserId. So, if I go to the setting and log out that will clean UserId and will not go to login view. I don't know why.

The code:

- (IBAction)resetKeychain:(id)sender {

    UIActionSheet *actionSheet = [[UIActionSheet alloc] 
                 initWithTitle:@"Are you sure you want to logout?" 
                 delegate:self 
                 cancelButtonTitle:@"Cancel" 
                 destructiveButtonTitle:@"Logout"
                 otherButtonTitles:nil];
    actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
    [actionSheet showFromTabBar:self.tabBarController.tabBar];
    [actionSheet release];

}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (buttonIndex ==0) {
        //logout
        NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
        //delete user ID fro user Defaults
        [defaults setObject:nil forKey:@"UserId"];
        //redirect to login view

        NewClassMoonAppDelegate * appsDelegate =[[UIApplication sharedApplication] delegate];
        [appsDelegate.window addSubview:[appsDelegate.login view]];

    }
}
Joe C
  • 3,506
  • 2
  • 21
  • 32
Montaser El-sawy
  • 800
  • 1
  • 8
  • 14
  • 2
    There is no such thing as a "perfect solution." Remember, the Best is the enemy of the Good. – Eric Jan 31 '13 at 18:50

3 Answers3

8

From what I can interpret from you question, which needs to be formatted and made coherent by the way, I believe that:

a) your @"UserID" value is not syncing with NSUserDefaults because you are not calling the -synchronize method. NSUserDefaults will update its in-memory key-value store, but will not write it to disk meaning that it's lost at an arbitrary time.

b) The fact that it is not going to the loginView could be to do with any few reasons, most likely that it is already a subview of your UIWindow. So, instead of reusing the login property in your app delegate, create a new instance variable of the View Controller, and set that as the rootViewController instead.

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {

    if (buttonIndex == 0) {
        NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:nil forKey:@"UserId"];
        [defaults synchronize];
        //redirect to login view

        NewClassMoonAppDelegate * appsDelegate =[[UIApplication sharedApplication] delegate];
        LoginViewController *login = [[LoginViewController alloc] initWithNibName...];
        [appsDelegate.window setRootViewController:nil];
        [appsDelegate.window setRootViewController:login];

    }
}
max_
  • 24,076
  • 39
  • 122
  • 211
  • Hey max_,your solution is great, but i do have a doubt, do i need to remove all other MVC's from the memory that i loaded before login out of the app? if not what happens to those MVC's? will they be in memory ? how this scenario should be handled? – RockandRoll Sep 10 '14 at 06:07
  • Any of those presented by the rootViewController and the rootViewController itself will be deallocated from memory. This will not be immediate as you may be retaining a reference elsewhere in the app, or the compiler may not be ready to do so. – max_ Sep 10 '14 at 19:20
1

Swift:

From max_'s answer with some changes:

let objectsToSave: [String] = [obj1, obj2, obj3]
for key in objectsToSave {
    NSUserDefaults.standardUserDefaults().removeObjectForKey(key)
}

 let appsDelegate = UIApplication.sharedApplication().delegate
 let storyboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
 let newLoginVC: LoginViewController = storyboard.instantiateInitialViewController() as! LoginViewController
 appsDelegate?.window!!.rootViewController = nil
 appsDelegate?.window!!.rootViewController = newLoginVC

EDIT: The only changes I've made are just that I initialize newLoginVC through Storyboards instead of initWitName.

gabuchan
  • 785
  • 1
  • 7
  • 18
  • please explain some more, why the change and what you achieve with it. – davejal Dec 16 '15 at 02:52
  • This solution works to navigate back to the loginVC, however, view controllers that have been allocated for the previous user session are not deallocated when the logout occurs. How can we deallocate all view controllers? – Chris Oct 11 '18 at 14:52
0

Make property of UINavigation controller and synthesize it, And write below code on logout button

AppDelegate * appDelegateObj =[[UIApplication sharedApplication] delegate];
    login *loginObj = [[login alloc]initWithNibName:@"login" bundle:nil];
    [appDelegateObj.window setRootViewController:nil];
    navObj=[[UINavigationController alloc]initWithRootViewController:loginObj];
    [appDelegateObj.window setRootViewController:navObj];
amar
  • 175
  • 3
  • 19
  • Why is `UINavigationController` required? The OP does not present the Login controller in a navigation stack. Other than that, I do not see any additions to the other answers already posted. – UditS Apr 06 '16 at 13:44