considérez le scénario suivant: J'ai une application basée sur un storyboard. J'ajoute un objet ViewController au storyboard, ajoute les fichiers de classe de ce ViewController au projet et spécifie le nom de la nouvelle classe dans l'inspecteur d'identité d'IB. Maintenant, comment vais-je faire référence à ce ViewController par programme à partir de AppDelegate? J'ai créé une variable avec la classe appropriée et l'ai convertie en propriété IBOutlet, mais je ne vois aucun moyen de faire référence au nouveau ViewController dans le code. Toute tentative de glisser-déposer d'une connexion ne fonctionne pas. .
c'est-à-dire que je peux accéder à ViewController de base dans AppDelegate comme ceci
(MyViewController*) self.window.rootViewController
mais qu'en est-il des autres ViewController contenus dans le storyboard?
Regardez la documentation pour -[UIStoryboard instantiateViewControllerWithIdentifier:]
. Cela vous permet d'instancier un contrôleur de vue à partir de votre scénario en utilisant l'identifiant que vous avez défini dans l'inspecteur d'attributs IB:
EDITED pour ajouter un exemple de code:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
bundle: nil];
MyViewController *controller = (MyViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: @"<Controller ID>"];
Si vous utilisez XCode
5, vous devriez le faire différemment.
UIViewController
dans UIStoryboard
Identity Inspector
dans le volet supérieur droitUse Storyboard ID
case à cocherStoryboard ID
champEnsuite, écrivez votre code.
// Override point for customization after application launch.
if (<your implementation>) {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main"
bundle: nil];
YourViewController *yourController = (YourViewController *)[mainStoryboard
instantiateViewControllerWithIdentifier:@"YourViewControllerID"];
self.window.rootViewController = yourController;
}
return YES;
Généralement, le système doit gérer l'instanciation du contrôleur de vue avec un storyboard. Ce que vous voulez, c'est parcourir la hiérarchie de viewController en saisissant une référence à la self.window.rootViewController
_ par opposition à l’initialisation des contrôleurs de vue, qui devraient déjà être initialisés correctement si vous avez correctement configuré votre storyboard.
Donc, supposons que votre rootViewController
soit un UINavigationController et que vous souhaitiez ensuite envoyer quelque chose à son contrôleur de vue supérieure, vous le feriez comme cela dans votre didFinishLaunchingWithOptions
de votre AppDelegate:
UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
MyViewController *myVC = (MyViewController *)nav.topViewController;
myVC.data = self.data;
Dans Swift si serait très similaire:
let nav = self.window.rootViewController as! UINavigationController;
let myVC = nav.topViewController as! MyViewController
myVc.data = self.data
Vous ne devriez vraiment pas initialiser les contrôleurs de vue à l'aide des identifiants de storyboard du délégué de l'application, à moins de vouloir contourner la manière normale de charger le storyboard et de charger vous-même tout le storyboard. Si vous devez initialiser des scènes à partir d'AppDelegate, vous ferez probablement quelque chose de mal. Je veux dire, imaginons que vous vouliez, pour une raison quelconque, envoyer des données à un contrôleur de vue de manière très distante, l'AppDelegate ne devrait pas atteindre la pile de contrôleur de vue pour définir des données. Ce n'est pas son affaire. Son métier est le rootViewController. Laissez le rootViewController gérer ses propres enfants! Donc, si je contournais le processus normal de chargement du storyboard par le système en supprimant les références à celui-ci dans le fichier info.plist, au mieux, instancierait rootViewController à l'aide de instantiateViewControllerWithIdentifier:
, et éventuellement sa racine s'il s'agit d'un conteneur, comme un UINavigationController. Ce que vous voulez éviter, c'est d'instancier des contrôleurs de vue déjà instanciés par le storyboard. C'est un problème que je vois beaucoup. En bref, je suis en désaccord avec la réponse acceptée. C'est incorrect à moins que les affiches ne suppriment le chargement du storyboard de l'info.plist car vous aurez chargé 2 storyboards autrement, ce qui n'a aucun sens. Ce n'est probablement pas une fuite de mémoire, car le système a initialisé la scène racine et l'a assignée à la fenêtre, mais vous l'avez ensuite réinstallée et réaffectée. Votre application a pris un très mauvais départ!
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
self.window.rootViewController = [storyboard instantiateInitialViewController];