2012-04-23 25 views
20

Estoy creando una aplicación de cliente web IOS 5.1 que usa un guión gráfico. Una de mis acciones es "cerrar la sesión", durante la cual quiero restablecer mi vista de raíz a la vista inicial creada por la vista raíz del Guión gráfico. (Cuando inicia sesión, algunos elementos de vista se eliminan o agregan en función de quién es usted; cuando cierra la sesión, quiero restablecerlos a sus valores predeterminados, que he especificado en el guión gráfico)Restablecimiento de Storyboard al cerrar sesión

Me doy cuenta que podía restablecer/volver a agregar mediante programación todos los elementos, pero ¿de qué sirve el guión gráfico? Me imagino que tiene que haber una manera de volver a la realidad al volver a cargar el archivo de vista, ¿verdad?

+0

¿Alguna vez resolvió esto? Tengo precisamente la misma necesidad de esto ... –

Respuesta

28

Encontré que el siguiente enfoque funciona para mí. Tenga en cuenta que uso ARC, sin embargo, no estoy seguro de si esto tiene mucho que ver con la solución. En primer lugar, en la clase de delegado de la aplicación, en application:didFinishLaunchingWithOptions: capturo la instancia Storyboard inital con la siguiente línea de código:

_initalStoryboard = self.window.rootViewController.storyboard; 

(Obviamente no es una variable de instancia UIStoryboard* _initalStoryboard;)

Luego he definido la siguiente función en mi aplicación delegado:

- (void)resetWindowToInitialView 
{ 
    for (UIView* view in self.window.subviews) 
    { 
     [view removeFromSuperview]; 
    } 

    UIViewController* initialScene = [_initalStoryboard instantiateInitialViewController]; 
    self.window.rootViewController = initialScene; 
} 

Tenga en cuenta el bucle en el que remueve todos subvistas de window. La documentación UIWindow RootViewController afirma:

Si la ventana tiene una jerarquía de vistas existentes, los viejos son vistas eliminado antes de instalar los nuevos.

Sin embargo, no he encontrado que este sea el caso ... por lo que elimino las vistas existentes de forma explícita antes de asignar un nuevo controlador raíz. No he encontrado ningún efecto secundario preocupante o pérdidas de memoria con este método. No soy de ninguna manera un experto en la magia de UIKit, por lo que le sugiero que pruebe y vuelva a probar esta solución si planea usarla usted mismo. Saludos

+0

Quería probar esto, pero no mostrar cómo llamar a la función desde un controlador cuando se presiona un botón. – gdubs

+2

Consulte esta pregunta ASÍ: http://stackoverflow.com/questions/1184146/getting-a-reference-to-the-uiapplication-delegate Muestra cómo puede obtener una referencia al delegado de su aplicación - en su caso lo usarás en el controlador de vista de tu escena. Por lo tanto, en el controlador táctil de su botón tendrá algo como: MyApplicationDelegate * appDelegate = (MyApplicationDelegate *) [[UIApplication sharedApplication] delegate]; [appDelegate resetWindowToInitialView]; –

+2

gracias jefe .... – gdubs

1

El siguiente funciona muy bien para mí, si se utiliza una estructura basada en NavController:

UIWindow *window = [[UIApplication sharedApplication].windows firstObject]; 
UINavigationController *navController = (UINavigationController *)window.rootViewController; 
UIViewController *vc = [navController.storyboard instantiateViewControllerWithIdentifier:@"Login"]; 
navController.viewControllers = @[vc]; 

Tiene que asignar el guión gráfico de identificación "Login" para su Login VC para que esto funcione.

0

Los siguientes obras para mí, si uso una estructura basada en UISplitViewController (probado en iOS 8+):

Quitar Storyboard de Proyectos general ->despliegue Info, por lo que el menú desplegable se parece a la a continuación y debe configurar el guión gráfico en el código.

Deployment Info Empty Main Interface

En algún lugar de AppDelegate.m

- (void)setupViewControllers 
{ 
    // check for thread, as this method might be called by other (e.g. logout) logic 
    if ([NSThread currentThread] != [NSThread mainThread]) { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self setupViewControllers]; 
     }); 
     return; 
    } 

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; 
    UIViewController *vc =[storyboard instantiateInitialViewController]; 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.window.rootViewController = vc; 

    // configure split vc 
    // Note: I reference split vc for my own purpose, but it is your mater of choice 
    self.splitViewController = (UISplitViewController *)self.window.rootViewController; 
    self.splitViewController.delegate = self; 
    self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible; 
    self.splitViewController.preferredPrimaryColumnWidthFraction = 0.5; 

    [self.window makeKeyAndVisible]; 
} 

para evitar duplicados de código, llamar a esta función desde application:didFinishLaunchingWithOptions: como una primera configuración

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    // some code... 
    [self setupViewControllers]; 
    // Optional: add splash view (e.g. [self addSplashView];) 
    // some code... 
} 

Dentro de un controlador de vista que esté listo para presente la interfaz de usuario para el usuario, elimine la vista de bienvenida.Por ejemplo (en Swift):

override func viewDidAppear(animated: Bool) { 
    super.viewDidAppear(animated) 

    if !AppSession.currentSession().isLoggedIn() { 
     presentLoginViewController(false, completion: {()->Void in 
      self.removeSplash() 
     }) 
    } 
    else { 
     removeSplash() 
    } 

    // some code... 
} 

private func removeSplash() { 
    if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate { 
     appDelegate.removeSplashView() 
    } 
} 
Cuestiones relacionadas