Condicionalmente, inicie en diferentes lugares en el guión gráfico de AppDelegate

Tengo un guión gráfico configurado con inicio de sesión activo y controlador de vista principal, este último es el controlador de vista al que se dirige al usuario cuando el inicio de sesión es exitoso. Mi objective es mostrar el controlador de vista principal de inmediato si la autenticación (almacenada en el llavero) es exitosa, y mostrar el controlador de vista de inicio de sesión si la autenticación falló. Básicamente, quiero hacer esto en mi AppDelegate:

// url request & response work fine, assume success is a BOOL here // that indicates whether login was successful or not if (success) { // 'push' main view controller } else { // 'push' login view controller } 

Sé sobre el método performSegueWithIdentifier: pero este método es un método de instancia de UIViewController, por lo que no se puede llamar desde AppDelegate. ¿Cómo hago esto usando mi storyboard existente?

EDITAR:

El controlador de vista inicial del guion gráfico ahora es un controlador de navegación que no está conectado a nada. Utilicé el setRootViewController: distinción porque MainIdentifier es un UITabBarController. Entonces, así es como se ven mis líneas:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL isLoggedIn = ...; // got from server response NSString *segueId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier"; UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil]; UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:segueId]; if (isLoggedIn) { [self.window setRootViewController:initViewController]; } else { [(UINavigationController *)self.window.rootViewController pushViewController:initViewController animated:NO]; } return YES; } 

Sugerencias / mejoras son bienvenidas!

Supongo que su guión gráfico está configurado como el “guión gráfico principal” (clave UIMainStoryboardFile en su Info.plist). En ese caso, UIKit cargará el guión gráfico y establecerá su controlador de vista inicial como el controlador de vista raíz de su ventana antes de enviar la application:didFinishLaunchingWithOptions: a su AppDelegate.

También asumo que el controlador de vista inicial en su guión gráfico es el controlador de navegación, sobre el cual desea presionar su controlador de vista principal o de inicio de sesión.

Puede solicitarle a su ventana su controlador de vista raíz y enviarle el performSegueWithIdentifier:sender: :

 NSString *segueId = success ? @"pushMain" : @"pushLogin"; [self.window.rootViewController performSegueWithIdentifier:segueId sender:self]; 

Estoy sorprendido de algunas de las soluciones que se sugieren aquí.

Realmente no hay necesidad de controladores de navegación ficticios en su guión gráfico, ocultando vistas y segues de encendido en viewDidAppear: o cualquier otro truco.

Si no tiene configurado el guión gráfico en su archivo plist, debe crear usted mismo la ventana y el controlador de la vista raíz :

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL isLoggedIn = ...; // from your server response NSString *storyboardId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier"; UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil]; UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:storyboardId]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.rootViewController = initViewController; [self.window makeKeyAndVisible]; return YES; } 

Si el guión gráfico está configurado en la lista de la aplicación, la ventana y el controlador de vista raíz ya estarán configurados por la aplicación de tiempo: se invocó didFinishLaunching: y se llamará a makeKeyAndVisible en la ventana por usted.

En ese caso, es aún más simple:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL isLoggedIn = ...; // from your server response NSString *storyboardId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier"; self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:storyboardId]; return YES; } 

SI el punto de entrada de su storyboard no es un UINavigationController :

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //Your View Controller Identifiers defined in Interface Builder NSString *firstViewControllerIdentifier = @"LoginViewController"; NSString *secondViewControllerIdentifier = @"MainMenuViewController"; //check if the key exists and its value BOOL appHasLaunchedOnce = [[NSUserDefaults standardUserDefaults] boolForKey:@"appHasLaunchedOnce"]; //if the key doesn't exist or its value is NO if (!appHasLaunchedOnce) { //set its value to YES [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"appHasLaunchedOnce"]; [[NSUserDefaults standardUserDefaults] synchronize]; } //check which view controller identifier should be used NSString *viewControllerIdentifier = appHasLaunchedOnce ? secondViewControllerIdentifier : firstViewControllerIdentifier; //IF THE STORYBOARD EXISTS IN YOUR INFO.PLIST FILE AND YOU USE A SINGLE STORYBOARD UIStoryboard *storyboard = self.window.rootViewController.storyboard; //IF THE STORYBOARD DOESN'T EXIST IN YOUR INFO.PLIST FILE OR IF YOU USE MULTIPLE STORYBOARDS //UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"YOUR_STORYBOARD_FILE_NAME" bundle:nil]; //instantiate the view controller UIViewController *presentedViewController = [storyboard instantiateViewControllerWithIdentifier:viewControllerIdentifier]; //IF YOU DON'T USE A NAVIGATION CONTROLLER: [self.window setRootViewController:presentedViewController]; return YES; } 

SI el punto de entrada de su storyboard ES un UINavigationController reemplace:

 //IF YOU DON'T USE A NAVIGATION CONTROLLER: [self.window setRootViewController:presentedViewController]; 

con:

 //IF YOU USE A NAVIGATION CONTROLLER AS THE ENTRY POINT IN YOUR STORYBOARD: UINavigationController *navController = (UINavigationController *)self.window.rootViewController; [navController pushViewController:presentedViewController animated:NO]; 

En su application:didFinishLaunchingWithOptions AppDelegate application:didFinishLaunchingWithOptions método application:didFinishLaunchingWithOptions , antes de la línea return YES , agregue:

 UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController; YourStartingViewController *yourStartingViewController = [[navigationController viewControllers] objectAtIndex:0]; [yourStartingViewController performSegueWithIdentifier:@"YourSegueIdentifier" sender:self]; 

Reemplace YourStartingViewController con el nombre de su primera clase de controlador de vista real (la que no desea que aparezca necesariamente) y YourSegueIdentifier con el nombre real de la transición entre ese controlador de inicio y el que realmente desea iniciar (el siguiente el segue).

Envuelva ese código en un condicional si no siempre quiere que suceda.

Dado que ya está usando un Storyboard, puede usar esto para presentarle al usuario MyViewController, un controlador personalizado (reducir un poco la respuesta de followben ).

En AppDelegate.m :

 -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { MyCustomViewController *controller = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"MyCustomViewController"]; // now configure the controller with a model, etc. self.window.rootViewController = controller; return YES; } 

La cadena que se pasa para instanciar ViewControllerWithIdentifier se refiere a Storyboard ID, que se puede establecer en el constructor de interfaz:

enter image description here

Simplemente envuelva esto en lógica según sea necesario.

Sin embargo, si comienzas con un UINavigationController, este enfoque no te dará controles de navegación.

Para ‘saltar hacia adelante’ desde el punto de partida de un controlador de navegación configurado a través del constructor de interfaz, use este enfoque:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UINavigationController *navigation = (UINavigationController *) self.window.rootViewController; [navigation.visibleViewController performSegueWithIdentifier:@"my-named-segue" sender:nil]; return YES; } 

¿Por qué no tener la pantalla de inicio de sesión que aparece primero, comprobar si el usuario ya está conectado y pulsar la siguiente pantalla inmediatamente? Todo en el ViewDidLoad.

Implementación rápida de lo mismo:

Si usa UINavigationController como punto de entrada en el guión gráfico

 let storyboard = UIStoryboard(name: "Main", bundle: nil) var rootViewController = self.window!.rootViewController as! UINavigationController; if(loginCondition == true){ let profileController = storyboard.instantiateViewControllerWithIdentifier("ProfileController") as? ProfileController rootViewController.pushViewController(profileController!, animated: true) } else { let loginController = storyboard.instantiateViewControllerWithIdentifier("LoginController") as? LoginController rootViewController.pushViewController(loginController!, animated: true) } 

Esta es la solución que funcionó en iOS7. Para acelerar la carga inicial y no hacer ninguna carga innecesaria, tengo un UIViewcontroller completamente vacío llamado “DUMMY” en mi archivo Storyboard. Entonces puedo usar el siguiente código:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; NSString* controllerId = @"Publications"; if (![NSUserDefaults.standardUserDefaults boolForKey:@"hasSeenIntroduction"]) { controllerId = @"Introduction"; } else if (![NSUserDefaults.standardUserDefaults boolForKey:@"hasDonePersonalizationOrLogin"]) { controllerId = @"PersonalizeIntro"; } if ([AppDelegate isLuc]) { controllerId = @"LoginStart"; } if ([AppDelegate isBart] || [AppDelegate isBartiPhone4]) { controllerId = @"Publications"; } UIViewController* controller = [storyboard instantiateViewControllerWithIdentifier:controllerId]; self.window.rootViewController = controller; return YES; } 

Sugiero crear un nuevo controlador MainViewController que sea Root View Controller of Navigation Controller. Para hacerlo, solo mantenga el control, luego arrastre la conexión entre el Controlador de navegación y MainViewController, elija ‘Relación – Controlador de vista raíz’ desde el prompt.

En MainViewController:

 - (void)viewDidLoad { [super viewDidLoad]; if (isLoggedIn) { [self performSegueWithIdentifier:@"HomeSegue" sender:nil]; } else { [self performSegueWithIdentifier:@"LoginSegue" sender:nil]; } } 

Recuerde crear divisiones entre MainViewController con los controladores de vista Inicio y Inicio de sesión. Espero que esto ayude. 🙂

Después de probar muchos métodos diferentes, pude resolver este problema con esto:

 -(void)viewWillAppear:(BOOL)animated { // Check if user is already logged in NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; if ([[prefs objectForKey:@"log"] intValue] == 1) { self.view.hidden = YES; } } -(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; // Check if user is already logged in NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; if ([[prefs objectForKey:@"log"] intValue] == 1) { [self performSegueWithIdentifier:@"homeSeg3" sender:self]; } } -(void)viewDidUnload { self.view.hidden = NO; }