que pasa para los limpiar las gratis datos conversaciones ccleaner cache borro borran app ios login uistoryboard logout clear
LoginExample

ios - para - que pasa si borro los datos de facebook



Las mejores prácticas para la pantalla de inicio de sesión de Storyboard, el manejo de la limpieza de datos al cerrar la sesión (13)

Aquí está mi solución Swifty para cualquier futuro espectador.

1) Cree un protocolo para manejar las funciones de inicio y cierre de sesión:

protocol LoginFlowHandler { func handleLogin(withWindow window: UIWindow?) func handleLogout(withWindow window: UIWindow? }

2) Extienda dicho protocolo y proporcione la funcionalidad aquí para cerrar sesión:

extension LoginFlowHandler { func handleLogin(withWindow window: UIWindow?) { if let _ = AppState.shared.currentUserId { //User has logged in before, cache and continue self.showMainApp(withWindow: window) } else { //No user information, show login flow self.showLogin(withWindow: window) } } func handleLogout(withWindow window: UIWindow?) { AppState.shared.signOut() showLogin(withWindow: window) } func showLogin(withWindow window: UIWindow?) { window?.subviews.forEach { $0.removeFromSuperview() } window?.rootViewController = nil window?.rootViewController = R.storyboard.login.instantiateInitialViewController() window?.makeKeyAndVisible() } func showMainApp(withWindow window: UIWindow?) { window?.rootViewController = nil window?.rootViewController = R.storyboard.mainTabBar.instantiateInitialViewController() window?.makeKeyAndVisible() } }

3) Luego puedo adaptar mi AppDelegate al protocolo LoginFlowHandler y llamar a handleLogin al inicio:

class AppDelegate: UIResponder, UIApplicationDelegate, LoginFlowHandler { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { window = UIWindow.init(frame: UIScreen.main.bounds) initialiseServices() handleLogin(withWindow: window) return true } }

A partir de aquí, mi extensión de protocolo manejará la lógica o determinará si el usuario inició sesión o no, y luego cambiará el windowsViewView Controll en consecuencia.

Estoy construyendo una aplicación para iOS usando un Storyboard. El controlador de vista raíz es un controlador de barra de pestañas. Estoy creando el proceso de inicio / cierre de sesión, y en su mayoría funciona bien, pero tengo algunos problemas. Necesito saber la mejor manera de configurar todo esto.

Quiero lograr lo siguiente:

  1. Muestra una pantalla de inicio de sesión la primera vez que se lanza la aplicación. Cuando inicien sesión, vaya a la primera pestaña del controlador de la barra de pestañas.
  2. Cada vez que inicien la aplicación, verifique si han iniciado sesión y vaya directamente a la primera pestaña del controlador de la barra de pestañas de la raíz.
  3. Cuando hacen clic manualmente en un botón de cierre de sesión, muestran la pantalla de inicio de sesión y borran todos los datos de los controladores de visualización.

Lo que he hecho hasta ahora es configurar el controlador de vista raíz en el controlador de la barra de pestañas y crear un segmento personalizado para mi controlador de vista de inicio de sesión. Dentro de mi clase del controlador de la barra de pestañas, viewDidAppear si han iniciado sesión dentro del método viewDidAppear y realizo el segue: [self performSegueWithIdentifier:@"pushLogin" sender:self];

También configuro una notificación para cuando se debe realizar la acción de cierre de sesión: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutAccount) name:@"logoutAccount" object:nil];

Al cerrar la sesión, [self setSelectedIndex:0] las credenciales del llavero, ejecuto [self setSelectedIndex:0] y realizo el segue para mostrar nuevamente el controlador de vista de inicio de sesión.

Todo esto funciona bien, pero me pregunto: ¿ debería esta lógica estar en el AppDelegate? También tengo dos problemas:

  • La primera vez que inician la aplicación , el controlador de la barra de pestañas se muestra brevemente antes de que se realice la operación. He intentado mover el código a viewWillAppear pero el segmento no funcionará tan pronto.
  • Cuando cierran la sesión, todos los datos todavía están dentro de todos los controladores de vista. Si inician sesión en una cuenta nueva, los datos de la cuenta anterior aún se muestran hasta que se actualizan. Necesito una forma de borrar esto fácilmente en el cierre de sesión.

Estoy abierto a volver a trabajar esto. He considerado convertir la pantalla de inicio de sesión en el controlador de vista raíz, o crear un controlador de navegación en AppDelegate para manejar todo ... No estoy seguro de cuál es el mejor método en este momento.


En Xcode 7 puedes tener múltiples storyBoards. Será mejor si puede mantener el flujo de inicio de sesión en un guión gráfico separado.

Esto se puede hacer usando SELECT VIEWCONTROLLER> Editor> Refactor to Storyboard

Y aquí está la versión Swift para configurar una vista como RootViewContoller-

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate appDelegate.window!.rootViewController = newRootViewController let rootViewController: UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("LoginViewController")


Esto es lo que terminé haciendo para lograr todo. Lo único que debe considerar además de esto es (a) el proceso de inicio de sesión y (b) donde está almacenando los datos de su aplicación (en este caso, usé un singleton).

Como puede ver, el controlador de vista raíz es mi controlador de pestaña principal . Hice esto porque después de que el usuario haya iniciado sesión, quiero que la aplicación se inicie directamente en la primera pestaña. (Esto evita cualquier "parpadeo" donde la vista de inicio de sesión se muestra temporalmente).

AppDelegate.m

En este archivo, compruebo si el usuario ya ha iniciado sesión. En caso contrario, presiono el controlador de vista de inicio de sesión. También manejo el proceso de cierre de sesión, donde borro datos y muestro la vista de inicio de sesión.

- (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

Aquí, si el inicio de sesión es exitoso, simplemente descarto la vista y envío una notificación.

-(void) loginWasSuccessful { // Send notification [[NSNotificationCenter defaultCenter] postNotificationName:@"loginSuccessful" object:self]; // Dismiss login screen [self dismissViewControllerAnimated:YES completion:nil]; }


Estoy en la misma situación que usted y la solución que encontré para limpiar los datos es eliminar todas las cosas CoreData en las que confían mis controladores de vista para dibujar su información. Pero todavía encontré que este enfoque es muy malo, creo que se puede lograr una forma más elegante de hacerlo sin guiones gráficos y usando solo código para administrar las transiciones entre los controladores de vista.

Encontré este proyecto en Github que hace todo esto solo por código y es bastante fácil de entender. Usan un menú lateral parecido a Facebook y lo que hacen es cambiar el controlador de la vista central dependiendo de si el usuario ha iniciado sesión o no. Cuando el usuario cierra la sesión, appDelegate elimina los datos de CoreData y vuelve a configurar el controlador de vista principal en la pantalla de inicio de sesión.


Gracias a la solución de bhavya. Hubo dos respuestas sobre swift, pero esas no son muy intactas. Tengo que hacer eso en el swift3.Below es el código principal.

En AppDelegate.swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. // seclect the mainStoryBoard entry by whthere user is login. let userDefaults = UserDefaults.standard if let isLogin: Bool = userDefaults.value(forKey:Common.isLoginKey) as! Bool? { if (!isLogin) { self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LogIn") } }else { self.window?.rootViewController = mainStoryboard.instantiateViewController(withIdentifier: "LogIn") } return true }

En SignUpViewController.swift

@IBAction func userLogin(_ sender: UIButton) { //handle your login work UserDefaults.standard.setValue(true, forKey: Common.isLoginKey) let delegateTemp = UIApplication.shared.delegate delegateTemp?.window!?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Main") }

En la función logOutAction

@IBAction func logOutAction(_ sender: UIButton) { UserDefaults.standard.setValue(false, forKey: Common.isLoginKey) UIApplication.shared.delegate?.window!?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() }


Lo uso para comprobar el primer lanzamiento:

- (NSInteger) checkForFirstLaunch { NSInteger result = 0; //no first launch // Get current version ("Bundle Version") from the default Info.plist file NSString *currentVersion = (NSString*)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; NSArray *prevStartupVersions = [[NSUserDefaults standardUserDefaults] arrayForKey:@"prevStartupVersions"]; if (prevStartupVersions == nil) { // Starting up for first time with NO pre-existing installs (e.g., fresh // install of some version) [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:currentVersion] forKey:@"prevStartupVersions"]; result = 1; //first launch of the app } else { if (![prevStartupVersions containsObject:currentVersion]) { // Starting up for first time with this version of the app. This // means a different version of the app was alread installed once // and started. NSMutableArray *updatedPrevStartVersions = [NSMutableArray arrayWithArray:prevStartupVersions]; [updatedPrevStartVersions addObject:currentVersion]; [[NSUserDefaults standardUserDefaults] setObject:updatedPrevStartVersions forKey:@"prevStartupVersions"]; result = 2; //first launch of this version of the app } } // Save changes to disk [[NSUserDefaults standardUserDefaults] synchronize]; return result; }

(Si el usuario elimina la aplicación y la vuelve a instalar, cuenta como un primer lanzamiento)

En el AppDelegate compruebo el primer lanzamiento y creo un controlador de navegación con las pantallas de inicio de sesión (inicio de sesión y registro), que coloco en la parte superior de la ventana principal actual:

[self.window makeKeyAndVisible]; if (firstLaunch == 1) { UINavigationController *_login = [[UINavigationController alloc] initWithRootViewController:loginController]; [self.window.rootViewController presentViewController:_login animated:NO completion:nil]; }

Como esto se encuentra en la parte superior del controlador de vista normal, es independiente del resto de la aplicación y, si ya no lo necesita, puede descartar el controlador de vista. Y también puede presentar la vista de esta manera, si el usuario presiona un botón manualmente.

Por cierto: guardo los datos de inicio de sesión de mis usuarios de esta manera:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"com.youridentifier" accessGroup:nil]; [keychainItem setObject:password forKey:(__bridge id)(kSecValueData)]; [keychainItem setObject:email forKey:(__bridge id)(kSecAttrAccount)];

Para el cierre de sesión: cambié lejos de CoreData (demasiado lento) y uso NSArrays y NSDictionaries para administrar mis datos ahora. Cerrar sesión solo significa vaciar esos arrays y diccionarios. Además, me aseguro de configurar mis datos en viewWillAppear.

Eso es.


No me gustó la respuesta de bhavya porque usé AppDelegate dentro de View Controllers y la configuración de rootViewController no tiene animación. Y la respuesta de Trevor tiene problemas con el controlador de vista parpadeante en iOS8.

UPD 18/07/2015

AppDelegate dentro de los controladores de vista:

Cambiar el estado de AppDelegate (propiedades) dentro del controlador de vista rompe la encapsulación.

Muy simple jerarquía de objetos en cada proyecto de iOS:

AppDelegate (posee window y rootViewController )

ViewController ( view )

Está bien que los objetos de la parte superior cambien los objetos de la parte inferior, porque los están creando. Pero no está bien si los objetos en la parte inferior cambian los objetos por encima de ellos (describí algunos principios básicos de programación / OOP: DIP (Principio de inversión de dependencia: el módulo de alto nivel no debe depender del módulo de bajo nivel, pero sí de las abstracciones) ).

Si algún objeto cambia algún objeto en esta jerarquía, tarde o temprano habrá un lío en el código. Puede que esté bien en los proyectos pequeños, pero no es divertido explorar este lío en los proyectos de bits =]

UPD 18/07/2015

UINavigationController animaciones modales de controlador utilizando UINavigationController (tl; dr: verifique el project ).

Estoy usando UINavigationController para presentar todos los controladores en mi aplicación. Inicialmente mostré el controlador de la vista de inicio de sesión en la pila de navegación con una animación simple de inserción / pop. Entonces decidí cambiarlo a modal con cambios mínimos.

Cómo funciona:

  1. El controlador de vista inicial (o self.window.rootViewController ) es UINavigationController con ProgressViewController como rootViewController . Estoy mostrando ProgressViewController porque DataModel puede tardar un tiempo en inicializarse porque está en la pila de datos central como en este article (me gusta mucho este enfoque).

  2. AppDelegate es responsable de obtener actualizaciones de estado de inicio de sesión.

  3. DataModel maneja el inicio / cierre de sesión del usuario y AppDelegate está observando su propiedad userLoggedIn a través de KVO. Podría decirse que no es el mejor método para hacer esto, pero funciona para mí. (Por qué KVO es malo, puede consultar this o este artículo (¿Por qué no usar notificaciones? Parte).

  4. ModalDismissAnimator y ModalPresentAnimator se utilizan para personalizar la animación de inserción predeterminada.

Cómo funciona la lógica de los animadores:

  1. AppDelegate se establece como un delegado de self.window.rootViewController (que es UINavigationController).

  2. AppDelegate devuelve uno de los animadores en -[AppDelegate navigationController:animationControllerForOperation:fromViewController:toViewController:] si es necesario.

  3. Los animadores implementan los -transitionDuration: y -animateTransition: -[ModalPresentAnimator animateTransition:] :

    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; [[transitionContext containerView] addSubview:toViewController.view]; CGRect frame = toViewController.view.frame; CGRect toFrame = frame; frame.origin.y = CGRectGetHeight(frame); toViewController.view.frame = frame; [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^ { toViewController.view.frame = toFrame; } completion:^(BOOL finished) { [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; }]; }

Proyecto de prueba está project .


No se recomienda hacer esto desde el delegado de la aplicación. AppDelegate gestiona el ciclo de vida de la aplicación relacionado con el inicio, la suspensión, la finalización, etc. Sugiero hacer esto desde su controlador de vista inicial en viewDidAppear . Puede self.presentViewController y self.dismissViewController desde el controlador de vista de inicio de sesión. Almacene una clave bool en NSUserDefaults para ver si se está iniciando por primera vez.


Tuve un problema similar para resolver en una aplicación y utilicé el siguiente método. No utilicé notificaciones para manejar la navegación.

Tengo tres guiones gráficos en la aplicación.

  1. Guión gráfico de la pantalla de inicio - para inicializar la aplicación y verificar si el usuario ya ha iniciado sesión
  2. Storyboard de inicio de sesión - para manejar el flujo de inicio de sesión de usuario
  3. Tabulador de la barra de pestañas: para mostrar el contenido de la aplicación

Mi guión gráfico inicial en la aplicación es el guión gráfico de pantalla de bienvenida. Tengo el controlador de navegación como raíz del inicio de sesión y el guión gráfico de la barra de pestañas para manejar las navegaciones del controlador de vista.

Creé una clase de navegador para manejar la navegación de la aplicación y se ve así:

class Navigator: NSObject {    static func moveTo(_ destinationViewController: UIViewController, from sourceViewController: UIViewController, transitionStyle: UIModalTransitionStyle? = .crossDissolve, completion: (() -> ())? = nil) {                DispatchQueue.main.async {            if var topController = UIApplication.shared.keyWindow?.rootViewController {                while let presentedViewController = topController.presentedViewController {                    topController = presentedViewController                }                                destinationViewController.modalTransitionStyle = (transitionStyle ?? nil)!                sourceViewController.present(destinationViewController, animated: true, completion: completion)            }        }    } }

Veamos los posibles escenarios:

  • Primer lanzamiento de la aplicación; La pantalla de bienvenida se cargará donde verifico si el usuario ya ha iniciado sesión. Luego, la pantalla de inicio de sesión se cargará utilizando la clase Navigator de la siguiente manera;

Como tengo el controlador de navegación como raíz, crea una instancia del controlador de navegación como controlador de vista inicial.

let loginSB = UIStoryboard(name: "splash", bundle: nil) let loginNav = loginSB.instantiateInitialViewcontroller() as! UINavigationController Navigator.moveTo(loginNav, from: self)

Esto elimina el guión gráfico de slpash de la raíz de la ventana de la aplicación y lo reemplaza con el guión gráfico de inicio de sesión.

Desde el inicio del guión gráfico, cuando el usuario ha iniciado sesión correctamente, guardo los datos del usuario en Valores predeterminados del usuario e inicializo un Singleton UserData para acceder a los detalles del usuario. Luego, el guión gráfico de la barra de pestañas se carga utilizando el método del navegador.

Let tabBarSB = UIStoryboard(name: "tabBar", bundle: nil) let tabBarNav = tabBarSB.instantiateInitialViewcontroller() as! UINavigationController Navigator.moveTo(tabBarNav, from: self)

Ahora el usuario cierra la sesión desde la pantalla de configuración en la barra de pestañas. Borro todos los datos de usuario guardados y navego a la pantalla de inicio de sesión.

let loginSB = UIStoryboard(name: "splash", bundle: nil) let loginNav = loginSB.instantiateInitialViewcontroller() as! UINavigationController Navigator.moveTo(loginNav, from: self)

  • El usuario está conectado y la fuerza mata la aplicación

Cuando el usuario inicie la aplicación, se cargará la pantalla de bienvenida. Verifico si el usuario ha iniciado sesión y accedo a los datos de usuario de los valores predeterminados del usuario. Luego inicialice el Singleton UserData y muestra la barra de pestañas en lugar de la pantalla de inicio de sesión.


introduzca la descripción de la imagen aquí

En la aplicación delegado.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault]; NSString *identifier; BOOL isSaved = [[NSUserDefaults standardUserDefaults] boolForKey:@"loginSaved"]; if (isSaved) { //identifier=@"homeViewControllerId"; UIWindow* mainWindow=[[[UIApplication sharedApplication] delegate] window]; UITabBarController *tabBarVC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"TabBarVC"]; mainWindow.rootViewController=tabBarVC; } else { identifier=@"loginViewControllerId"; UIStoryboard * storyboardobj=[UIStoryboard storyboardWithName:@"Main" bundle:nil]; UIViewController *screen = [storyboardobj instantiateViewControllerWithIdentifier:identifier]; UINavigationController *navigationController=[[UINavigationController alloc] initWithRootViewController:screen]; self.window.rootViewController = navigationController; [self.window makeKeyAndVisible]; } return YES;

}

ver controlador.m a la vista se cargó

- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. UIBarButtonItem* barButton = [[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStyleDone target:self action:@selector(logoutButtonClicked:)]; [self.navigationItem setLeftBarButtonItem:barButton];

}

En acción de botón de cierre de sesión

-(void)logoutButtonClicked:(id)sender{ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Do you want to logout?" preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:@"Logout" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setBool:NO forKey:@"loginSaved"]; [[NSUserDefaults standardUserDefaults] synchronize]; AppDelegate *appDelegate = [UIApplication sharedApplication].delegate; UIStoryboard * storyboardobj=[UIStoryboard storyboardWithName:@"Main" bundle:nil]; UIViewController *screen = [storyboardobj instantiateViewControllerWithIdentifier:@"loginViewControllerId"]; [appDelegate.window setRootViewController:screen]; }]]; [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { [self dismissViewControllerAnimated:YES completion:nil]; }]]; dispatch_async(dispatch_get_main_queue(), ^ { [self presentViewController:alertController animated:YES completion:nil]; });}


Después de crear LoginViewController y TabBarController , debemos agregar un StoryboardID como " loginViewController " y " tabBarController " respectivamente

Entonces prefiero crear la estructura constante :

struct Constants { struct StoryboardID { static let signInViewController = "SignInViewController" static let mainTabBarController = "MainTabBarController" } struct kUserDefaults { static let isSignIn = "isSignIn" } }

En LoginViewController añadir IBAction :

@IBAction func tapSignInButton(_ sender: UIButton) { UserDefaults.standard.set(true, forKey: Constants.kUserDefaults.isSignIn) Switcher.updateRootViewController() }

En ProfileViewController añadir IBAction :

@IBAction func tapSignOutButton(_ sender: UIButton) { UserDefaults.standard.set(false, forKey: Constants.kUserDefaults.isSignIn) Switcher.updateRootViewController() }

En AppDelegate, agregue la línea de código en didFinishLaunchingWithOptions :

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { Switcher.updateRootViewController() return true }

Finalmente crear la clase Switcher :

import UIKit class Switcher { static func updateRootViewController() { let status = UserDefaults.standard.bool(forKey: Constants.kUserDefaults.isSignIn) var rootViewController : UIViewController? #if DEBUG print(status) #endif if (status == true) { let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil) let mainTabBarController = mainStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardID.mainTabBarController) as! MainTabBarController rootViewController = mainTabBarController } else { let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil) let signInViewController = mainStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardID.signInViewController) as! SignInViewController rootViewController = signInViewController } let appDelegate = UIApplication.shared.delegate as! AppDelegate appDelegate.window?.rootViewController = rootViewController } }

¡Eso es todo!


EDIT: Agregar acción de cierre de sesión.

1. En primer lugar preparar el archivo delegado de la aplicación.

AppDelegate.h

#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (nonatomic) BOOL authenticated; @end

AppDelegate.m

#import "AppDelegate.h" #import "User.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { User *userObj = [[User alloc] init]; self.authenticated = [userObj userAuthenticated]; return YES; }

2. Crea una clase llamada Usuario.

Usuario.h

#import <Foundation/Foundation.h> @interface User : NSObject - (void)loginWithUsername:(NSString *)username andPassword:(NSString *)password; - (void)logout; - (BOOL)userAuthenticated; @end

Usuario.m

#import "User.h" @implementation User - (void)loginWithUsername:(NSString *)username andPassword:(NSString *)password{ // Validate user here with your implementation // and notify the root controller [[NSNotificationCenter defaultCenter] postNotificationName:@"loginActionFinished" object:self userInfo:nil]; } - (void)logout{ // Here you can delete the account } - (BOOL)userAuthenticated { // This variable is only for testing // Here you have to implement a mechanism to manipulate this BOOL auth = NO; if (auth) { return YES; } return NO; }

3. Cree un nuevo controlador RootViewController y conecte con la primera vista, donde el botón de inicio de sesión está activo. Agregue también un ID de guión gráfico: "initialView".

RootViewController.h

#import <UIKit/UIKit.h> #import "LoginViewController.h" @protocol LoginViewProtocol <NSObject> - (void)dismissAndLoginView; @end @interface RootViewController : UIViewController @property (nonatomic, weak) id <LoginViewProtocol> delegate; @property (nonatomic, retain) LoginViewController *loginView; @end

RootViewController.m

#import "RootViewController.h" @interface RootViewController () @end @implementation RootViewController @synthesize loginView; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)loginBtnPressed:(id)sender { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loginActionFinished:) name:@"loginActionFinished" object:loginView]; } #pragma mark - Dismissing Delegate Methods -(void) loginActionFinished:(NSNotification*)notification { AppDelegate *authObj = (AppDelegate*)[[UIApplication sharedApplication] delegate]; authObj.authenticated = YES; [self dismissLoginAndShowProfile]; } - (void)dismissLoginAndShowProfile { [self dismissViewControllerAnimated:NO completion:^{ UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UITabBarController *tabView = [storyboard instantiateViewControllerWithIdentifier:@"profileView"]; [self presentViewController:tabView animated:YES completion:nil]; }]; } @end

4. Cree un nuevo controlador LoginViewController y conecte con la vista de inicio de sesión.

LoginViewController.h

#import <UIKit/UIKit.h> #import "User.h" @interface LoginViewController : UIViewController

LoginViewController.m

#import "LoginViewController.h" #import "AppDelegate.h" - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)submitBtnPressed:(id)sender { User *userObj = [[User alloc] init]; // Here you can get the data from login form // and proceed to authenticate process NSString *username = @"username retrieved through login form"; NSString *password = @"password retrieved through login form"; [userObj loginWithUsername:username andPassword:password]; } @end

5. Al final, agregue un nuevo controlador ProfileViewController y conecte con la vista de perfil en el tabViewController.

ProfileViewController.h

#import <UIKit/UIKit.h> @interface ProfileViewController : UIViewController @end

ProfileViewController.m

#import "ProfileViewController.h" #import "RootViewController.h" #import "AppDelegate.h" #import "User.h" @interface ProfileViewController () @end @implementation ProfileViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; } - (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if(![(AppDelegate*)[[UIApplication sharedApplication] delegate] authenticated]) { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; RootViewController *initView = (RootViewController*)[storyboard instantiateViewControllerWithIdentifier:@"initialView"]; [initView setModalPresentationStyle:UIModalPresentationFullScreen]; [self presentViewController:initView animated:NO completion:nil]; } else{ // proceed with the profile view } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)logoutAction:(id)sender { User *userObj = [[User alloc] init]; [userObj logout]; AppDelegate *authObj = (AppDelegate*)[[UIApplication sharedApplication] delegate]; authObj.authenticated = NO; UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; RootViewController *initView = (RootViewController*)[storyboard instantiateViewControllerWithIdentifier:@"initialView"]; [initView setModalPresentationStyle:UIModalPresentationFullScreen]; [self presentViewController:initView animated:NO completion:nil]; } @end

LoginExample es un proyecto de ejemplo para ayuda adicional.


En tu appDelegate.m dentro de tu didFinishLaunchingWithOptions

//authenticatedUser: check from NSUserDefaults User credential if its present then set your navigation flow accordingly if (authenticatedUser) { self.window.rootViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateInitialViewController]; } else { UIViewController* rootController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"LoginViewController"]; UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController]; self.window.rootViewController = navigation; }

En el archivo SignUpViewController.m

- (IBAction)actionSignup:(id)sender { AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate]; appDelegateTemp.window.rootViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateInitialViewController]; }

En el archivo MyTabThreeViewController.m

- (IBAction)actionLogout:(id)sender { // Delete User credential from NSUserDefaults and other data related to user AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate]; UIViewController* rootController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"LoginViewController"]; UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController]; appDelegateTemp.window.rootViewController = navigation; }

Versión Swift 4

didFinishLaunchingWithOptions en el delegado de la aplicación, asumiendo que su controlador de vista inicial es el TabbarController firmado.

if Auth.auth().currentUser == nil { let rootController = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "WelcomeNavigation") self.window?.rootViewController = rootController } return true

En Registrarse ver controlador:

@IBAction func actionSignup(_ sender: Any) { let appDelegateTemp = UIApplication.shared.delegate as? AppDelegate appDelegateTemp?.window?.rootViewController = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateInitialViewController() }

MyTabThreeViewController

//Remove user credentials guard let appDel = UIApplication.shared.delegate as? AppDelegate else { return } let rootController = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "WelcomeNavigation") appDel.window?.rootViewController = rootController