Выбор альтернативного контроллера первого взгляда из панели рассказов при запуске приложения
Я только что начал программировать на iOS, и до сих пор учебники и ответы, которые я нашел здесь, были большой помощью для продвижения вперед. Тем не менее, эта конкретная проблема натирала меня всю ночь, и я не могу найти ответ, который "чувствует себя хорошо".
Я пишу приложение, которое подключается к удаленному сервису, и пользователям необходимо войти в систему, прежде чем они смогут его использовать. Когда они начинают использовать приложение, их первым представлением должен быть диалог входа в систему; когда они прошли проверку подлинности, они сразу же видят обзорную страницу.
В проекте используются доски объявлений, которые, как я считаю, являются отличной функцией, поэтому большую часть кода, который выбирает и загружает контроллер корневого представления, уже позаботился. Я думал, что лучшим местом для добавления моей логики является метод application:didFinishLaunchingWithOptions:
AppDelegate
:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
// select my root view controller here based on credentials present or not
return YES;
}
Но это вызвало два вопроса:
-
Внутри этого конкретного метода делегата контроллер корневого представления уже выбран (и загружен?) на основе панели рассказов. Могу ли я переместиться на более раннее место в процессе загрузки, чтобы переопределить выбор первого диспетчера, или это бы невольно усложняло вопросы?
-
Чтобы переопределить первый контроллер представления, мне нужна ссылка на панель рассказов, но я не мог найти лучшего способа, чем использовать конструктор storyboardWithName:bundle:
UIStoryboard
. Это неправильно, приложение должно уже иметь ссылку на панель рассказов, но как я могу получить к нему доступ?
Обновление
Я разработал второй вопрос, который у меня был, так как нашел свой ответ здесь:
UIStoryboard: каков правильный способ получения активной раскадровки?
NSBundle *bundle = [NSBundle mainBundle];
NSString *sbFile = [bundle objectForInfoDictionaryKey:@"UIMainStoryboardFile"];
UIStoryboard *sb = [UIStoryboard storyboardWithName:sbFile bundle:bundle];
Вышеупомянутый создаст новый экземпляр панели рассказов; для получения активного экземпляра это намного проще:
UIStoryboard *sb = [[self.window rootViewController] storyboard];
В самом файле панели рассказов вам необходимо установить идентификатор для представления, которое вы хотите загрузить, например. LoginDialog
. После этого вы создаете представление следующим образом:
LoginViewController *login = [sb instantiateViewControllerWithIdentifier:@"LoginDialog"];
[self.window setRootViewController:login];
Внутри другого контроллера просмотра достаточно:
UIStoryboard *sb = self.storyboard;
LoginViewController *login = [sb instantiateViewControllerWithIdentifier:@"LoginDialog"];
[self presentViewController:login animated:NO completion:nil];
Ответы
Ответ 1
Вы можете просто reset контроллер корневого представления окна
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
if(your_condition) {
UIViewController *newRoot = [your implementation];
self.window.rootViewController = newRoot;
}
return YES;
}
Это работает для меня, Xcode5.0.1
Ответ 2
У меня такой же сценарий, как у вас. Мое приложение использует UINavigationController
в качестве контроллера корневого представления. Если пользователь вошел в систему, я хочу представить его с помощью NotLoggedInViewController
, а если он войдет в систему, я хочу показать LoggedInViewController
.
В раскадровке UINavigationController
может быть только один ребенок, поэтому вы должны иметь возможность программно назначать ему еще один контроллер корневого представления.
Начну с создания пользовательского класса контроллера навигации, назовите его MyNavigationController
. В раскадровке я назначаю этот настраиваемый класс объекту навигационного контроллера.
В раскадровке я затем моделирую оба контроллера представления и подключаю один из них к объекту навигационного контроллера. Поскольку я должен иметь возможность получить к ним доступ из моего кода позже, я назначаю каждому из них идентификатор с помощью инспектора XCode справа. Эти идентификаторы могут быть произвольными строками, но для простых вещей я просто использую имена классов.
Наконец, я реализую метод viewDidLoad
в классе MyNavigationController
:
BOOL isLoggedIn = ...;
- (void)viewDidLoad {
id rootController;
if (isLoggedIn) {
rootController = [self.storyboard instantiateViewControllerWithIdentifier:@"LoggedInViewController"];
} else {
rootController = [self.storyboard instantiateViewControllerWithIdentifier:@"NotLoggedInViewController"];
}
self.viewControllers = [NSArray arrayWithObjects:rootController, nil];
}
Ответ 3
Я едва использовал раскадровку и, вероятно, это не точный ответ на ваш вопрос. Но я предлагаю вам каким-то образом то, что я сделал в своем проекте, созданном без использования раскадровки.
В didFinishLaunchingWithOptions
AuthenticationViewController - первое загруженное представление. Он запрашивает учетные данные. После ввода он будет вводить фактические ViewControllers (а именно TabBar & все..), используемые проектом.
Интересная функция, добавленная в проект, - когда вы вводите учетные данные, я вытащил UIAleretView
, который просит пользователя выбрать один из трех вариантов.
- Сохранить учетные данные без кода доступа
- Сохранить учетные данные с кодом доступа
- Не сохранять учетные данные
Здесь код пропуска - это всего лишь 4-значный номер, введенный пользователем. Всякий раз, когда он хочет "Сохранить учетные данные с кодом доступа", я pushViewController
, который показывает InstPad instap стандартной клавиатуры и popviewController
, когда он заканчивает ввод PIN-кода. Если пользователь "Не сохранять учетные данные", а затем во время воспроизведения приложения хочет перейти на другие параметры проверки подлинности, я добавил последнюю вкладку TabBarController в качестве вкладки "Настройки", в которой я разрешаю пользователю выбирать одну из опций проверки подлинности, t24 > в начале запуска приложения после входа в систему.
Не забывайте сохранять учетные данные в keychain
В двух словах,
- AuthenticationViewController- > проверить, хранятся ли учетные данные в цепочке ключей
1,1. Если не сохранить (т.е. 3. Не сохранять учетные данные) → затем показать страницу входа.
1,2. Если учетные данные сохраняются в keychain- > извлекать их и видеть, связана ли их с кодом доступа.
1.2.1. Если он связан с кодом доступа (то есть 2. Сохранить учетные данные с кодом доступа
) → затем отобразите страницу с паролем.
1.2.2. Если он не привязан (1. Сохраните учетные данные без кода доступа) → затем покажите/загрузите иерархию проекта TabBarController
или другие материалы. здесь на самом деле ваше приложение запускается.
Ответ 4
Когда основная раскадровка уже загружена, это просто вопрос поиска ссылки, чтобы я мог создать экземпляр другого контроллера корневого представления:
UIStoryboard *mainStoryboard = self.window.rootViewController.storyboard;
self.window.rootViewController = [mainStoryboard
instantiateViewControllerWithIdentifier:@"view-controller-id"];