Раскадровка-см. 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>"];
если вы используете
XCode
5, Вы должны сделать это другим способом.
- выберите
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 раскадровки в противном случае, что не имеет смысла. Вероятно, это не утечка памяти, потому что система инициализировала корневую сцену и назначила ее окну, но затем вы пришли и снова создал экземпляр и назначил его снова. Ваше приложение находится в довольно плохом начале!