Раскадровка-см. ViewController в AppDelegate
рассмотрим следующий сценарий: у меня есть приложение на основе раскадровки. Я добавляю объект ViewController в раскадровку, добавляю файлы классов для этого ViewController в проект и указываю имя нового класса в инспекторе идентификации IB. Теперь как я буду ссылаться на этот ViewController программно из AppDelegate? Я сделал переменную с соответствующим классом и превратил ее в свойство IBOutlet, но я не вижу никакого способа ссылаться на новый ViewController в коде-любая попытка ctrl-перетащить соединение не работает.
т. е. в AppDelegate я могу добраться до базового ViewController, как это
(MyViewController*) self.window.rootViewController
но как насчет любого другого ViewController, содержащегося в раскадровке?
3 ответа:
посмотреть документация на
-[UIStoryboard instantiateViewControllerWithIdentifier:]. Это позволяет создать экземпляр контроллера вида из раскадровки с помощью идентификатора, заданного в Инспекторе атрибутов IB:
отредактировано, чтобы добавить пример кода:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle: nil]; MyViewController *controller = (MyViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: @"<Controller ID>"];
если вы используете
XCode5, Вы должны сделать это другим способом.
- выберите
UIViewControllerнаUIStoryboard- перейти к
Identity Inspectorна правой верхней панели- Регистрация
Use Storyboard IDфлажок- напишите уникальный идентификатор в
Storyboard IDполезатем писать свой код.
// 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;
как правило, система должна обрабатывать экземпляр контроллера вида с помощью раскадровки. То, что вы хотите, чтобы пересечь иерархию viewController, захватив ссылку на
self.window.rootViewControllerв отличие от инициализации контроллеров представления, которые уже должны быть инициализированы правильно, если вы правильно настроили раскадровку.Итак, допустим, ваша
rootViewControllerявляется UINavigationController, а затем вы хотите отправить что-то на свой контроллер верхнего вида, вы бы сделали это так ваш AppDelegate вdidFinishLaunchingWithOptions:UINavigationController *nav = (UINavigationController *) self.window.rootViewController; MyViewController *myVC = (MyViewController *)nav.topViewController; myVC.data = self.data;в Swift если бы было очень похоже:
let nav = self.window.rootViewController as! UINavigationController; let myVC = nav.topViewController as! MyViewController myVc.data = self.dataвы действительно не должны инициализировать контроллеры представления с помощью идентификаторов раскадровки из делегата приложения, если вы не хотите обойти обычный способ загрузки раскадровки и загрузить всю раскадровку самостоятельно. Если вам нужно инициализировать сцены из AppDelegate, вы, скорее всего, делаете что-то неправильно. Я имею в виду, что вы по какой-то причине хотите отправить данные в контроллер вида вниз по стеку AppDelegate не должен достигать пути в стек контроллера вида для установки данных. Это не его дело. Это бизнес-это rootViewController. Пусть rootViewController обрабатывает своих собственных детей! Итак, если бы я обходил обычный процесс загрузки раскадровки системой, удаляя ссылки на нее в информации.plist-файл, я бы в лучшем случае создал экземпляр rootViewController с помощью
instantiateViewControllerWithIdentifier:, и, возможно, его корень, если это контейнер, как UINavigationController. Что? вы хотите избежать создания экземпляров контроллеров представления, которые уже были созданы раскадровкой. Это проблема, которую я вижу много. Короче говоря, я не согласен с принятым ответом. Это неверно, если плакаты не означают удаление загрузки раскадровки из информации.plist так как вы загрузили 2 раскадровки в противном случае, что не имеет смысла. Вероятно, это не утечка памяти, потому что система инициализировала корневую сцену и назначила ее окну, но затем вы пришли и снова создал экземпляр и назначил его снова. Ваше приложение находится в довольно плохом начале!
