Best Practices For Storyboard Login Screen, Handling Clearing of Data Upon Logout

Best practices for Storyboard login screen, handling clearing of data upon logout

Here is what I ended up doing to accomplish everything. The only thing you need to consider in addition to this is (a) the login process and (b) where you are storing your app data (in this case, I used a singleton).

Storyboard showing login view controller and main tab controller

As you can see, the root view controller is my Main Tab Controller. I did this because after the user has logged in, I want the app to launch directly to the first tab. (This avoids any "flicker" where the login view shows temporarily.)

AppDelegate.m

In this file, I check whether the user is already logged in. If not, I push the login view controller. I also handle the logout process, where I clear data and show the login view.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

// Show login view if not logged in already
if(![AppData isLoggedIn]) {
[self showLoginScreen:NO];
}

return YES;
}

-(void) showLoginScreen:(BOOL)animated
{

// Get login screen from storyboard and present it
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
LoginViewController *viewController = (LoginViewController *)[storyboard instantiateViewControllerWithIdentifier:@"loginScreen"];
[self.window makeKeyAndVisible];
[self.window.rootViewController presentViewController:viewController
animated:animated
completion:nil];
}

-(void) logout
{
// Remove data from singleton (where all my app data is stored)
[AppData clearData];

// Reset view controller (this will quickly clear all the views)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MainTabControllerViewController *viewController = (MainTabControllerViewController *)[storyboard instantiateViewControllerWithIdentifier:@"mainView"];
[self.window setRootViewController:viewController];

// Show login screen
[self showLoginScreen:NO];

}

LoginViewController.m

Here, if the login is successful, I simply dismiss the view and send a notification.

-(void) loginWasSuccessful
{

// Send notification
[[NSNotificationCenter defaultCenter] postNotificationName:@"loginSuccessful" object:self];

// Dismiss login screen
[self dismissViewControllerAnimated:YES completion:nil];

}

Best practices for Storyboard login screen, handling clearing of data upon logout

Here is what I ended up doing to accomplish everything. The only thing you need to consider in addition to this is (a) the login process and (b) where you are storing your app data (in this case, I used a singleton).

Storyboard showing login view controller and main tab controller

As you can see, the root view controller is my Main Tab Controller. I did this because after the user has logged in, I want the app to launch directly to the first tab. (This avoids any "flicker" where the login view shows temporarily.)

AppDelegate.m

In this file, I check whether the user is already logged in. If not, I push the login view controller. I also handle the logout process, where I clear data and show the login view.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

// Show login view if not logged in already
if(![AppData isLoggedIn]) {
[self showLoginScreen:NO];
}

return YES;
}

-(void) showLoginScreen:(BOOL)animated
{

// Get login screen from storyboard and present it
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
LoginViewController *viewController = (LoginViewController *)[storyboard instantiateViewControllerWithIdentifier:@"loginScreen"];
[self.window makeKeyAndVisible];
[self.window.rootViewController presentViewController:viewController
animated:animated
completion:nil];
}

-(void) logout
{
// Remove data from singleton (where all my app data is stored)
[AppData clearData];

// Reset view controller (this will quickly clear all the views)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MainTabControllerViewController *viewController = (MainTabControllerViewController *)[storyboard instantiateViewControllerWithIdentifier:@"mainView"];
[self.window setRootViewController:viewController];

// Show login screen
[self showLoginScreen:NO];

}

LoginViewController.m

Here, if the login is successful, I simply dismiss the view and send a notification.

-(void) loginWasSuccessful
{

// Send notification
[[NSNotificationCenter defaultCenter] postNotificationName:@"loginSuccessful" object:self];

// Dismiss login screen
[self dismissViewControllerAnimated:YES completion:nil];

}

Access login screen view controller after logging out from a cell

I think the best thing to do in your case is delegate callback.

You have to define a protocol and implement it in your View Controller

protocol LoginDelegate {

func didPressLogOut()
}

class SettingsViewController : LoginDelegate {

func didPressLogOut() {

// Display an Alert to user to confirm logging out
let actionSheet = UIAlertController(title: "Log Out", message: "Are you sure you want to log out?", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
actionSheet.addAction(UIAlertAction(title: "Log Out", style: .destructive, handler: { _ in
AuthManager.shared.logOut(completion: {success in
DispatchQueue.main.async {
if (success) {
// Go to login after logout
let loginVC = self.storyboard?.instantiateViewController(identifier: "login")
loginVC?.modalPresentationStyle = .fullScreen
self.present(loginVC!, animated: true, completion: {
self.navigationController?.popToRootViewController(animated: false)
self.tabBarController?.selectedIndex = 0
})
}
else {
// Error Occurd
fatalError("Could not log out user")
}
}
})
}))

present(actionSheet, animated: true)
}
}

When initializing your custom cell in the view controller, make sure to see the delegate to the viewcontroller

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SettingsTableViewCellIdentifier", for: indexPath) as! SettingsTableViewCell
cell.loginDelegate = self

// Rest of the cell setup code

return cell
}

Then in your cell class, on the IBAction, you just call the delegate method.

class SettingsTableViewCell {

var loginDelegate: LoginDelegate?


@IBAction func logUserOut(_ sender: Any) {

// Callback to the delegate
self.loginDelegate?.didPressLogOut()
}
}

restoring iOS app to original state and clearing all data when user logs out

If you want to reset all of the tabs and return the apps to it's initial state after logging out, all you have to do is reset the UITabBarController's viewControllers property.

So if you are subclassing UITabBarController the following code should restore your app to its original state.

    self.viewControllers = @[self.viewControllerOne, self.viewControllerTwo, self.viewControllerThree];

From the documentation:

If you change the value of this property at runtime, the tab bar controller removes all of the old view controllers before installing the new ones. The tab bar items for the new view controllers are displayed immediately and are not animated into position.



Related Topics



Leave a reply



Submit