44 votes

Appeler la scène du storyboard de manière programmatique (sans avoir besoin de segue) ?

J'ai une scène modale de storyboard que je veux rendre accessible à toutes mes autres scènes. Créer une segue modale vers cette scène à partir de chaque scène de mon storyboard crée un grand désordre de chaînes qui vont partout. Existe-t-il un moyen de supprimer les séquences et d'appeler la scène de manière programmatique à la place ?

En gros, je veux faire quelque chose comme ça :

  MyNewViewController *myNewVC = [[MyNewViewController alloc] init];
  [self presentModalViewController:myNewVC animated:YES];

sauf qu'au lieu de créer et de pousser une classe de contrôleur de vue, je veux faire une transition modale vers une scène de storyboard "isolée" (non connectée avec un segue).

87voto

Darren Points 3714

Si, vous le pouvez. Faites quelque chose comme ceci pour obtenir l'accès au VC, puis poussez-le simplement de façon modale :

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];
MyNewViewController *myVC = (MyNewViewController *)[storyboard instantiateViewControllerWithIdentifier:@"myViewCont"];

0 votes

Est-ce que cela pousse la scène comme une vue modale (comme ce serait le cas avec une segue modale) ?

1 votes

Cela dépend de la façon dont vous le présentez. Utilisez [self presentModalViewController:myVC animated:YES] ; et il sera

0 votes

Merci. Une chose qui m'échappe... Qu'arrive-t-il à myVC juste après la deuxième ligne mais avant la ligne "presentModalViewController:myVC" ? Est-il simplement caché en arrière-plan ?

40voto

Charles Wilson Points 241

Remarque : la méthode presentModalViewController:animé est déprécié dans iOS 6.

Le nouveau code devrait se lire comme suit :

NSString * storyboardName = @"MainStoryboard_iPhone";
NSString * viewControllerID = @"ViewID";
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
MyViewController * controller = (MyViewController *)[storyboard instantiateViewControllerWithIdentifier:viewControllerID];
[self presentViewController:controller animated:YES completion:nil];

0 votes

Vous pouvez également utiliser self.storyboard si vous voulez vous assurer que vous utilisez le même storyboard.

0 votes

Un peu plus de détails sur votre première ligne. Bien que présent Modal ViewController:animated est Dépréciée, elle est remplacée par presentViewController:animated, sans le mot Modal au milieu du nom de la méthode. Cela peut ne pas être clair pour quelqu'un au premier coup d'œil, car les appels de fonction se ressemblent beaucoup.

19voto

Jeremy1026 Points 2348

Dans le storyboard, donnez un identifiant à votre contrôleur de vue (sous l'inspecteur des attributs) puis utilisez le code suivant pour faire avancer cette vue.

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"STORYBOARDNAME" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:@"VIEWCONTROLLERIDENTIFIER"];
[self presentModalViewController:vc animated:YES];

1 votes

Cela ne semble pas fonctionner lorsqu'il est appelé à partir d'un AppDelegate.

0 votes

@radven Les ViewControllers et leurs classes ne sont pas appelables depuis l'AppDelegate (je pense)...

1 votes

@RazorSharp vraiment ? Je fais appel aux VC tout le temps dans l'AppDelegate (selon les besoins). Par exemple (de mémoire), lorsque je configure un contrôleur de barre d'onglets racine et que je dois initialiser les contrôleurs de vue dans les onglets. Maintenant, pour que les choses s'affichent, vous devez travailler dans le délégué d'application qui présente les contrôleurs de vue racine, le tableau d'affichage, etc.

6voto

Alex Zavatone Points 901

J'ai un cas où je veux présenter un contrôleur de vue de la partie principale de l'application, qui contient les paramètres, l'aide, etc. Pour ce faire, je veux que ce soit dans un contrôleur de navigation, une sorte de petit module externe que nous pouvons appeler à partir d'un UIBarButtonItem.

Maintenant, cela peut être vers/dans le storyboard actuel, ou vers un autre, cela n'a pas d'importance.

Je veux le faire de cette façon, parce que je déteste le potentiel de spaghetti de lignes de transition partout dans mon storyboard.

Voici comment procéder.

- (IBAction)displaySettings:(id)sender
{
    LOG_SELECTOR() // google that for extra goodness

    // FYI, this can be done using a different storyboard like so.
    /*
     NSString * storyboardName = @"MainStoryboard_iPhone"; // possibly use device idiom?
     UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
     */

    // To push a new set of scenes with a new Navigation Controller, it is done like this:
    UINavigationController *settingsNC = [self.storyboard instantiateViewControllerWithIdentifier:@"Settings Nav Controller"];
    OBSettingsUIViewController *settingsVC = [self.storyboard instantiateViewControllerWithIdentifier:@"Settings root"];
    [settingsNC pushViewController:settingsVC animated:NO];

    [settingsNC setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];

    // Present the view controller;
    [self presentViewController:settingsNC animated:YES completion:NULL];
}

Dans les contrôleurs de vue présentés (ou dans une sous-classe du contrôleur de navigation), vous pouvez disposer d'un UIBarButtonItem qui permet ensuite de rejeter toute la hiérarchie de contrôleurs de vue présentés, comme suit :

- (IBAction)dismissThisVC:(id)sender {
     [self dismissViewControllerAnimated:YES completion:nil];
}

J'espère que cela aidera un certain nombre de personnes. A la vôtre.

1voto

supergegs Points 19

Je pense qu'avec iOS7, il est devenu très facile de l'implémenter via le storyboard.

Je suis en train de me renseigner sur les nouvelles fonctionnalités d'iOS7 et j'ai trouvé cette solution simple, mais elle aurait pu être pertinente même dans les versions antérieures, je n'en suis pas sûr.

Tout d'abord, vous devez connecter le VC de présentation avec le VC cible (c'est la seule connexion nécessaire), puis dans l'inspecteur d'attributs du storyboard, choisissez le style modal, dans l'inspecteur d'identité, donnez à votre VC un storyboardID et assurez-vous que vous avez coché la case "utiliser le storyboardID",

Si ce n'est pas encore le cas, ajoutez cette méthode à votre CVP :

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

   YourTargetVC * targetVC = 
         (YourTargetVC *)segue.destinationViewController;

   if(nil != targetVC) {

       //Do preparations here
   }

}

Maintenant, lorsque vous souhaitez montrer votre targetVC à partir de votre presentingVC, vous pouvez utiliser :

[self performSegueWithIdentifier:(NSString *) sender:(id)];

où l'identifiant est le storyboardID de votre viewController, et l'expéditeur est la vue qui a déclenché l'action, cette méthode invoquera la scène des storyboards, de sorte que l'élément [prepareForSegue: sender:] sera appelée, ce qui permettra d'effectuer les dernières modifications avant l'apparition du targetViewController.

3 votes

La question était "sans avoir besoin de segue", parce que "le storyboard crée un grand désordre de chaînes qui vont partout".

0 votes

Thnx, vous avez raison. Mais je pense que la question originale a été publiée avant la sortie de iOS7.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X