Estoy creando 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 de sesión / cierre de sesión, y en su mayoría funciona bien, pero tengo algunos problemas. Necesito saber la MEJOR forma de configurar todo esto.
Quiero lograr lo siguiente:
- Mostrar una pantalla de inicio de sesión la primera vez que se inicia la aplicación. Cuando inicien sesión, vaya a la primera pestaña del Controlador de barra de pestañas.
- Cada vez que inicien la aplicación después de eso, verifique si han iniciado sesión y salte directamente a la primera pestaña del Controlador de barra de pestañas raíz.
- 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 vista.
Lo que he hecho hasta ahora es configurar el controlador de vista raíz en el Controlador de barra de pestañas y crear un seguimiento personalizado para mi controlador de vista de inicio de sesión. Dentro de mi clase Tab Bar Controller, verifico si están conectados dentro del viewDidAppear
método y realizo el seguimiento:[self performSegueWithIdentifier:@"pushLogin" sender:self];
También configuré una notificación para cuando la acción de cierre de sesión debe realizarse: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutAccount) name:@"logoutAccount" object:nil];
Al cerrar sesión, borro las credenciales del llavero, ejecuto [self setSelectedIndex:0]
y realizo el seguimiento 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 barra de pestañas se muestra brevemente antes de realizar el seguimiento. He intentado mover el código
viewWillAppear
pero el segue no funcionará tan temprano. - 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 todavía se muestran hasta que se actualizan. Necesito una manera de borrar esto fácilmente al cerrar sesión.
Estoy abierto a reelaborar esto. He considerado hacer que la pantalla de inicio de sesión sea el controlador de vista raíz, o crear un controlador de navegación en AppDelegate para manejar todo ... Simplemente no estoy seguro de cuál es el mejor método en este momento.
Respuestas:
En su appDelegate.m dentro de didFinishLaunchingWithOptions
En el archivo SignUpViewController.m
En el archivo MyTabThreeViewController.m
Versión Swift 4
didFinishLaunchingWithOptions en el delegado de la aplicación, suponiendo que su controlador de vista inicial sea el TabbarController firmado.
En el controlador de vista de registro:
MyTabThreeViewController
fuente
AppDelegate
dentroUIViewController
y configurarwindow.rootViewController
allí. No considero esto como una "mejor práctica".-1
sin publicar una respuesta: stackoverflow.com/a/30664935/1226304AppDelegate
dentroUIViewController
-1 para almacenar la clave de inicio de sesiónNSUserDefaults
. ¡Es muy, muy inseguro para ese tipo de datos!Esto es lo que terminé haciendo para lograr todo. Lo único que debe tener en cuenta además de esto es (a) el proceso de inicio de sesión y (b) dónde está almacenando los datos de su aplicación (en este caso, utilicé 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 ha 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, verifico si el usuario ya inició sesión. Si no, presiono el controlador de vista de inicio de sesión. También manejo el proceso de cierre de sesión, donde borro los datos y muestro la vista de inicio de sesión.
LoginViewController.m
Aquí, si el inicio de sesión es exitoso, simplemente descarto la vista y envío una notificación.
fuente
[self.window makeKeyAndVisible]; [self.window.rootViewController presentViewController:viewController animated:animated completion:nil];
conself.window.rootViewController = viewController;
para evitar el parpadeo. Para animar eso, simplemente envuélvelo en un[UIView transitionWithView...];
EDITAR: Agregar acción de cierre de sesión.
1. En primer lugar, prepare el archivo delegado de la aplicación
AppDelegate.h
AppDelegate.m
2. Cree una clase llamada Usuario.
Usuario.h
Usuario.m
3. Cree un nuevo controlador RootViewController y conéctese con la primera vista, donde vive el botón de inicio de sesión. Agregue también una ID de Storyboard: "initialView".
RootViewController.h
RootViewController.m
4) Cree un nuevo controlador LoginViewController y conéctese con la vista de inicio de sesión.
LoginViewController.h
LoginViewController.m
5. Al final, agregue un nuevo controlador ProfileViewController y conéctese con la vista de perfil en la pestaña ViewController.
ProfileViewController.h
ProfileViewController.m
LoginExample es un proyecto de muestra para obtener ayuda adicional.
fuente
No me gustó la respuesta de bhavya por usar
AppDelegate
dentro de View Controllers y configurarrootViewController
no tiene animación. Y la respuesta de Trevor tiene problemas con el controlador de vista intermitente en iOS8.UPD 18/07/2015
AppDelegate dentro de View Controllers:
Cambiar el estado de AppDelegate (propiedades) dentro del controlador de vista interrumpe la encapsulación.
Jerarquía muy simple de objetos en cada proyecto de iOS:
AppDelegate (posee
window
yrootViewController
)ViewController (posee
view
)Está bien que los objetos de arriba cambien los objetos de abajo, porque los están creando. Pero no está bien si los objetos en la parte inferior cambian los objetos en la parte superior 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 deben depender de abstracciones) )
Si algún objeto cambiara cualquier objeto en esta jerarquía, tarde o temprano habrá un desorden en el código. Puede estar bien en los proyectos pequeños, pero no es divertido profundizar en este desastre en los proyectos de bits =]
UPD 18/07/2015
Repito las animaciones del controlador modal usando
UINavigationController
(tl; dr: verifique el proyecto ).Estoy usando
UINavigationController
para presentar todos los controladores en mi aplicación. Inicialmente, mostré el controlador de vista de inicio de sesión en la pila de navegación con animación push / pop simple. Entonces decidí cambiarlo a modal con cambios mínimos.Cómo funciona:
El controlador de vista inicial (o
self.window.rootViewController
) es UINavigationController con ProgressViewController como arootViewController
. Estoy mostrando ProgressViewController porque DataModel puede tardar un tiempo en inicializarse porque se encuentra en la pila de datos principales como en este artículo (realmente me gusta este enfoque).AppDelegate es responsable de obtener actualizaciones del estado de inicio de sesión.
DataModel maneja el inicio / cierre de sesión del usuario y AppDelegate está observando su
userLoggedIn
propiedad 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 este o este artículo (parte ¿Por qué no usar notificaciones?)).ModalDismissAnimator y ModalPresentAnimator se utilizan para personalizar la animación push predeterminada.
Cómo funciona la lógica de los animadores:
AppDelegate se establece como un delegado de
self.window.rootViewController
(que es UINavigationController).AppDelegate devuelve uno de los animadores
-[AppDelegate navigationController:animationControllerForOperation:fromViewController:toViewController:]
si es necesario.Implementación de animadores
-transitionDuration:
y-animateTransition:
métodos.-[ModalPresentAnimator animateTransition:]
:El proyecto de prueba está aquí .
fuente
AppDelegate
(me gustaría entender por qué lo hace), pero su comentario sobre la falta de animación es muy válido. Esto se puede resolver con esta respuesta: stackoverflow.com/questions/8053832/…UITabBarController
durante mucho tiempo. Probablemente comenzaría con un enfoque de ventana en lugar de manipular los controladores de vista.Aquí está mi solución Swifty para futuros espectadores.
1) Cree un protocolo para manejar las funciones de inicio y cierre de sesión:
2) Amplíe dicho protocolo y proporcione la funcionalidad aquí para cerrar sesión:
3) Entonces puedo conformar mi AppDelegate al protocolo LoginFlowHandler y llamar
handleLogin
al inicio:A partir de aquí, mi extensión de protocolo manejará la lógica o determinará si el usuario está conectado / desconectado, y luego cambiará el rootViewController de Windows en consecuencia.
fuente
LoginFlowHandler
. ¿Me estoy perdiendo de algo? Además, supongo que este código solo administra el inicio de sesión en el inicio. ¿Cómo gestiono el cierre de sesión desde un controlador de vista?AppState
Por lo tanto, esta implementación dependerá de cómo esté guardando sus datos de usuario en el disco.handleLogout
funcionalidad?LoginFlowHandler
protocolo. Entonces obtendrá alcance para poder llamar al método handleLogout. Vea mi paso 3 para ver un ejemplo de cómo hice eso para la clase AppDelegate.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 lanzamiento, la suspensión, la finalización, etc. Sugiero hacer esto desde su controlador de vista inicial en el
viewDidAppear
. Puedeself.presentViewController
yself.dismissViewController
desde el controlador de vista de inicio de sesión. Guarde unabool
claveNSUserDefaults
para ver si se inicia por primera vez.fuente
Después de crear LoginViewController y TabBarController , necesitamos agregar un StoryboardID como " loginViewController " y " tabBarController " respectivamente.
Entonces prefiero crear la estructura constante :
En LoginViewController agregue IBAction :
En ProfileViewController agregue IBAction :
En AppDelegate agregue una línea de código en didFinishLaunchingWithOptions :
Finalmente cree la clase Switcher :
¡Eso es todo!
fuente
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 independiente.
Esto se puede hacer usando SELECT VIEWCONTROLLER> Editor> Refactor to Storyboard
Y aquí está la versión Swift para configurar una vista como RootViewContoller-
fuente
Lo uso para verificar el primer lanzamiento:
(si el usuario elimina la aplicación y la vuelve a instalar, cuenta como un primer inicio)
En AppDelegate, compruebo el primer inicio y creo un controlador de navegación con las pantallas de inicio de sesión (inicio de sesión y registro), que coloco encima de la ventana principal actual:
Como esto está en la parte superior del controlador de vista normal, es independiente del resto de su aplicación y puede simplemente descartar el controlador de vista, si ya no lo necesita. 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:
Para cerrar sesión: me cambié de CoreData (demasiado lento) y uso NSArrays y NSDictionaries para administrar mis datos ahora. Cerrar sesión solo significa vaciar esas matrices y diccionarios. Además, me aseguro de configurar mis datos en viewWillAppear.
Eso es.
fuente
Estoy en la misma situación que usted y la solución que encontré para limpiar los datos es eliminar todas las cosas de CoreData en las que confían mis controladores de vista para dibujar su información. Pero todavía considero 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. Utilizan un menú lateral similar a Facebook y lo que hacen es cambiar el controlador de vista central dependiendo de si el usuario ha iniciado sesión o no. Cuando el usuario
appDelegate
cierra sesión, elimina los datos de CoreData y vuelve a establecer el controlador de vista principal en la pantalla de inicio de sesión.fuente
Tuve un problema similar que 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.
Mi guión gráfico inicial en la aplicación es guión gráfico de pantalla de bienvenida. Tengo el controlador de navegación como la 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 Navigator para manejar la navegación de la aplicación y se ve así:
Veamos los posibles escenarios:
Como tengo el controlador de navegación como raíz, instanciaré el controlador de navegación como controlador de vista inicial.
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 guión gráfico de inicio de sesión, cuando el usuario inicia sesión correctamente, guardo los datos del usuario en Valores predeterminados del usuario e inicializo un singleton de Datos de usuario 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.
Ahora el usuario cierra 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.
Cuando el usuario inicia la aplicación, se cargará la pantalla de bienvenida. Compruebo si el usuario ha iniciado sesión y accedo a los datos del usuario desde 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.
fuente
Gracias a la solución de bhavya. Ha habido dos respuestas sobre swift, pero esas no están muy intactas. Lo he hecho en swift3. Debajo está el código principal.
En AppDelegate.swift
En SignUpViewController.swift
En la función logOutAction
fuente
ingrese la descripción de la imagen aquí
En la aplicación Delegate.m
}
ver controlador.m En vista se cargó
}
En la acción del botón de cierre de sesión
fuente
NSUserDefaults
es muy, muy insegura para ese tipo de datos!