web-dev-qa-db-fra.com

Effectuer Segue sur ViewDidLoad

Dans iOS 5, j'ai un Storyboard avec un contrôleur de vue modal, que je voudrais afficher si c'est la première fois que l'utilisateur l'utilise dans l'application, puis je voudrais ignorer ce contrôleur de vue.

J'ai défini une clé NSDefault pour gérer cela, mais lorsque je vérifie si cela est défini, puis que j'utilise performSegueWithIdentifier pour lancer la séquence, rien ne se passe. Si je mets cette séquence derrière un bouton cela fonctionne très bien ...

56
adam0101

J'ai répondu à une question similaire où le développeur voulait montrer un écran de connexion au début. Je lui ai préparé un exemple de code que vous pouvez télécharger ici . La solution pour résoudre ce problème consiste à appeler les choses au bon moment si vous voulez afficher ce nouveau contrôleur de vue, vous verrez dans l'exemple que vous devez utiliser quelque chose comme ceci

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"LoginViewController"];
    [vc setModalPresentationStyle:UIModalPresentationFullScreen];

    [self presentModalViewController:vc animated:YES];
}

J'ai aussi une explication sur le fonctionnement des ligues et des storyboards que vous pouvez voir ici

47
Scott Sherwood

Le chargement dans ViewDidLoad a provoqué le clignotement de "sous-couche". J'ai résolu ce problème en chargeant mon Storyboard par programmation. Ainsi, sous Cible/Scénario principal - laissez ce champ vide. Ensuite, ajoutez ce qui suit:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Load Main App Screen
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    HomeScreenVC *homeScreenVC = [storyboard instantiateInitialViewController];
    self.window.rootViewController = homeScreenVC;
    [self.window makeKeyAndVisible];

    // Load Login/Signup View Controller
    UIViewController *mainLoginVC = [storyboard instantiateViewControllerWithIdentifier:@"MainLoginVC"];
    [mainLoginVC setModalPresentationStyle:UIModalPresentationFullScreen];
    [homeScreenVC presentModalViewController:mainLoginVC animated:NO];

    return YES;
}
42
bearMountain

Le problème est que vous ajoutez une deuxième vue à la hiérarchie avant que la première ne soit complètement ajoutée. Essayez de mettre votre code dans:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    // Present your modal from here
}

Après l'appel de [super viewDidAppear], vous devez modifier une vue entièrement chargée.

22
NJones

Il n'y a pas de problème principal lors de l'exécution de segments dans viewDidLoad (après l'appel de super bien sûr).

Le problème consiste à effectuer des étapes avant que la fenêtre de l'application ne soit visible .. Le UIViewController que vous souhaitez afficher fait partie du storyboard principal; il est donc chargé en mémoire avant que l'application ne commence à exécuter son code dans le délégué de l'application. Dans votre cas, viewDidLoad est appelé par iOS avant que la fenêtre de votre application ne reçoive le message: MakeKeyAndVisible.

La partie importante est la visibilité. Effectuer une transition dans une hiérarchie de vues dans laquelle la fenêtre n'est pas visible ne fait rien!

Vous pouvez essayer de faire quelque chose comme ça:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// The window initialized with hidden = YES, so in order to perform the segue we need to set this value to NO.
// After this action, the OS will add the window.rootViewController's view as a subview of the window.
self.window.hidden = NO;

[self.window.rootViewController performSegueWithIdentifier:_IDENTIFIER_ sender:self.window.rootViewController];

// Now that the window is not hidden, we must make it key.
[self.window makeKeyWindow];
return YES;
}
11
EladWeinson

UPDATE: cette solution ne fonctionne plus sous iOS 8.

Une façon correcte de résoudre votre problème consiste à déclencher le contrôleur de vue modal segue/present dans la méthode de délégué applicationDidBecomeActive: app ou dans un gestionnaire de notification UIApplicationDidBecomeActiveNotification.

La documentation d'Apple en fait conseille la même chose :

Si votre application était précédemment en arrière-plan, vous pouvez également l'utiliser pour actualiser l'interface utilisateur de votre application.

Cette solution présente l’avantage de fonctionner avec le mécanisme de chargement du storyboard principal, vous évitant ainsi de charger quoi que ce soit manuellement et d’écrire du code inutile.

J'utilise cette solution avec succès sur iOS 6.1, 7.0 et 7.1 et cela devrait fonctionner sur iOS 5 non plus.

10
Leon Deriglazov

C'est comme ça que je l'ai fait dans Swift. Cela masque également le contrôleur de vue.

override func viewWillAppear(animated: Bool) {
    let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()

    let isloggedIn = prefs.objectForKey("isLoggedIn") as? Bool
    if (isloggedIn != false) {
        self.view.hidden = true
    } else {
        self.view.hidden = false
    }
}

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

    let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()

    let isloggedIn = prefs.objectForKey("isLoggedIn") as? Bool
    if (isloggedIn != false) {
        println("this should work")
        self.performSegueWithIdentifier("Login", sender: self)
    }
}
5
Surge Pedroza

Pour Swift:

dispatch_async(dispatch_get_main_queue()) {
   self.performSegueWithIdentifier("toView2", sender: self)
}

Pour Swift 3:

DispatchQueue.main.async {
    self.performSegueWithIdentifier("toView2", sender: self)
}
5
pbaranski

Swift 3

override func viewWillAppear(_ animated: Bool) {
    if authPreference.isExist() == true {
        self.view.isHidden = true
    } else {
        self.view.isHidden = false
    }
}

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

    if authPreference.isExist() == true {
        navigateToSegue()
    }
}
2
Jaseem Abbas

J'ai eu le même problème. Avant de trouver cette question, j'ai résolu ce problème en utilisant async dans le fil principal. De cette façon, ce code sera appelé par le thread d'interface utilisateur juste après la création de la vue. 

dispatch_async(dispatch_get_main_queue(), ^{
        [self performSegueWithIdentifier:@"segueAlbums" sender:self];
    });

Ce code peut être appelé dans la méthode viewDidLoad.

1
GuillermoMP

Mise à jour pour Swift 3

L'extrait de code ci-dessous vous permet de charger le viewController de votre choix. Dans mon cas, il s'agissait d'un TabBarController si l'utilisateur possédait un jeton de connexion facebook valide. L'avantage de cette solution par rapport à l'autre solution Swift 3 est qu'elle est instantanée, sans scintillement de l'écran.

func applicationDidBecomeActive(_ application: UIApplication) {
    if FBSDKAccessToken.current() != nil {
        self.window?.rootViewController?.present((self.window?.rootViewController?.storyboard?.instantiateViewController(withIdentifier: "TabBarController"))!, animated: false, completion: nil)           
    }
}
1

La meilleure solution est de faire ceci:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];    
    [self performSegueWithIdentifier:@"NameSegue" sender:self];
}
0
nhegroj

J'ai adapté @bearMountain answer pour Swift 3.

func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    let yourInitialVC: UIViewController? = storyboard.instantiateViewController(withIdentifier: "TermsVC")
    window?.rootViewController = termsVC
    window?.makeKeyAndVisible()
    return true
}
0
Nathan Barreto