Раскадровка - см. ViewController в AppDelegate
рассмотрим следующий сценарий: у меня есть приложение на основе раскадровки. Я добавляю объект ViewController в раскадровку, добавляю файлы классов для этого ViewController в проект и указываю имя нового класса в инспекторе идентификации IB. Теперь, как я буду обращаться к этому ViewController программно из AppDelegate? Я сделал переменную с соответствующим классом и превратил ее в свойство IBOutlet, но я не вижу никакого способа ссылаться на новый ViewController в коде - любая попытка ctrl-drag connection не работает.
то есть. в AppDelegate я могу добраться до базового ViewController, такого как
(MyViewController*) self.window.rootViewController
но как насчет любого другого ViewController, содержащегося в раскадровке?
Ответы
Ответ 1
Посмотрите documentation для -[UIStoryboard instantiateViewControllerWithIdentifier:]
. Это позволяет вам создать экземпляр контроллера просмотра из раскадровки с помощью идентификатора, установленного в инспекторе атрибутов IB:
![enter image description here]()
EDITED добавить пример кода:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
bundle: nil];
MyViewController *controller = (MyViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: @"<Controller ID>"];
Ответ 2
Если вы используете 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;
Ответ 3
Как правило, система должна обрабатывать экземпляр контроллера представления с помощью раскадровки. Вы хотите пройти через иерархию 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 обрабатывает своих собственных детей! Итак, если я обходил процесс загрузки нормального раскадровки системой, удалив ссылки на него в файле info.plist, я бы максимально создал экземпляр rootViewController с помощью instantiateViewControllerWithIdentifier:
и, возможно, его root, если он является контейнером, например, UINavigationController. То, что вы хотите избежать, - это создавать экземпляры контроллеров представлений, которые уже были созданы с помощью раскадровки. Это проблема, которую я вижу много. Короче говоря, я не согласен с принятым ответом. Это неверно, если плакаты не позволяют удалить загрузку раскадровки из info.plist, поскольку в противном случае вы загрузите 2 раскадровки, что не имеет смысла. Вероятно, это не утечка памяти, потому что система инициализировала корневую сцену и назначила ее окну, но затем вы пришли и снова создали его и снова назначили. Ваше приложение отключено до очень плохого начала!
Ответ 4
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
self.window.rootViewController = [storyboard instantiateInitialViewController];