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).
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).
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
Having a Uitextfield in a Uitableviewcell
Importing Commoncrypto in a Swift Framework
How to Intercept Touches Events on a Mkmapview or Uiwebview Objects
Class Does Not Implement Its Superclass'S Required Members
How to Count Occurrences of an Element in a Swift Array
Nsdictionary With Ordered Keys
Swift Png Image Being Saved With Incorrect Orientation
Set Padding For Uitextfield With Uitextborderstylenone
Uiview Infinite 360 Degree Rotation Animation
Wkwebview Not Loading Local Files Under iOS 8
How to Have Stored Properties in Swift, the Same Way I Had on Objective-C
Openurl Not Work in Action Extension
Prevent Screen Capture in an iOS App
How to Insert New Cell into Uitableview in Swift
Push Notification Issue With iOS 10
How to Detect Avplayer and Get Url of Current Video from Wkwebview