Выбор альтернативного контроллера первого взгляда из панели рассказов при запуске приложения

Я только что начал программировать на 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"];