рассмотрим следующий сценарий: у меня есть приложение на основе раскадровки. Я добавляю объект ViewController в раскадровку, добавляю файлы классов для этого ViewController в проект и указываю имя нового класса в инспекторе идентичности IB. Как мне теперь программно обратиться к этому ViewController из AppDelegate? Я создал переменную с соответствующим классом и превратил ее в свойство IBOutlet, но я не вижу возможности ссылаться на новый ViewController в коде - любая попытка перетаскивания соединения с помощью Ctrl не работает ,
т.е. внутри AppDelegate я могу добраться до базового ViewController следующим образом
(MyViewController*) self.window.rootViewController
но как насчет любого другого ViewController, содержащегося в раскадровке?
iphone
objective-c
ios
uiviewcontroller
storyboard
Маттиас Д.
источник
источник
Ответы:
Посмотрите документацию для
-[UIStoryboard instantiateViewControllerWithIdentifier:]
. Это позволяет вам создать экземпляр контроллера представления из вашей раскадровки, используя идентификатор, который вы установили в инспекторе атрибутов IB:ИЗМЕНИТЬ, чтобы добавить пример кода:
источник
[[[self window] rootViewController] storyboard]
Согласно документам, это вернет «раскадровку, из которой произошел контроллер представления». (или ноль, если это не из раскадровки). Из этого UIStoryboard * вы можете использовать вызовы экземпляра, упомянутые @RobinSummerhill. Обратите внимание, что раскадровки создают новые экземпляры ваших viewControllers ( сцен ) по мере необходимости и не используют повторно те, которые были просмотрены ранее.Если вы используете
XCode
5, вы должны сделать это по-другому.UIViewController
вUIStoryboard
Identity Inspector
на правую верхнюю панельUse Storyboard ID
флажокStoryboard ID
полеЗатем напишите свой код.
источник
Как правило, система должна обрабатывать создание экземпляра контроллера представления с помощью раскадровки. Что вы хотите, так это пройти иерархию viewController, захватив ссылку на,
self.window.rootViewController
а не на инициализацию контроллеров представления, которые уже должны быть правильно инициализированы, если вы правильно настроили раскадровку.Итак, предположим, что вы
rootViewController
UINavigationController, а затем вы хотите отправить что-то в его контроллер верхнего вида, вы бы сделали это в своем AppDelegate следующим образомdidFinishLaunchingWithOptions
:В Swift if будет очень похоже:
Вам действительно не следует инициализировать контроллеры представления с использованием идентификаторов раскадровки от делегата приложения, если вы не хотите обойти обычный способ загрузки раскадровки и загрузить всю раскадровку самостоятельно. Если вам нужно инициализировать сцены из AppDelegate, вы, скорее всего, делаете что-то не так. Я имею в виду, что вы по какой-то причине хотите отправить данные в контроллер представления вниз по стеку, AppDelegate не должен попадать в стек контроллера представления для установки данных. Это не его дело. Это дело rootViewController. Позвольте rootViewController обрабатывать своих собственных потомков! Итак, если бы я обходил обычный процесс загрузки раскадровки системой, удаляя ссылки на нее в файле info.plist, я бы в лучшем случае создал экземпляр rootViewController, используя
instantiateViewControllerWithIdentifier:
, и, возможно, его корень, если это контейнер, например UINavigationController. Чего вы хотите избежать, так это создания экземпляров контроллеров представления, которые уже были созданы раскадровкой. Я часто вижу эту проблему. Короче не согласен с принятым ответом. Это неверно, если плакаты не предназначены для удаления загрузки раскадровки из info.plist, поскольку в противном случае вы загрузите 2 раскадровки, что не имеет смысла. Вероятно, это не утечка памяти, потому что система инициализировала корневую сцену и назначила ее окну, но затем вы пришли, создали ее снова и назначили снова. Ваше приложение запущено очень плохо!источник
источник