Как представить контроллер просмотра всплывающих окон / входа в систему с помощью раскадровки

Я видел этот вопрос в различных формах без четкого ответа. Я собираюсь спросить и ответить здесь. Моему приложению нужно выполнять работу при запуске … inits, несколько сетевых вызовов, логин и т. Д. Я не хочу, чтобы мой главный контроллер представления работал до тех пор, пока это не будет выполнено. Что хорошего для этого?

Требования:

  • iOS5 +, раскадровки, ARC.
  • основной вид vc не может появиться до тех пор, пока не будет выполнена работа по запуску.
  • хотите, чтобы выбор стилей перехода на главный vc выполнялся при запуске.
  • хотите сделать как можно больше макета в раскадровке.
  • код должен быть чистым, где-то очевидным.

2 Solutions collect form web for “Как представить контроллер просмотра всплывающих окон / входа в систему с помощью раскадровки”

EDIT, июль 2017 года. После первого написания я изменил свою практику на ту, где я запускаю задачи для своего собственного контроллера представления. В этом VC я проверяю условия запуска, при необходимости нажимаю «занятый» интерфейс и т. Д. На основании состояния при запуске я устанавливаю корень VC окна.

В дополнение к решению проблемы ОП этот подход имеет дополнительные преимущества, позволяющие лучше контролировать запуск UI и UI-переходов. Вот как это сделать:

В основной раскадровке добавьте новый VC, называемый LaunchViewController и сделайте его первоначальным vc. Дайте «реальный» первоначальный vc вашего приложения идентификатор типа «AppUI» (идентификаторы находятся на вкладке «Идентификация» в IB).

Идентифицируйте другие vcs, которые являются запусками основных потоков пользовательского интерфейса (например, регистрация / вход, учебное пособие и т. Д.) И дают эти описательные идентификаторы. (Некоторые предпочитают держать каждый поток в собственной раскадровке. Это хорошая практика, ИМО).

Еще одна приятная необязательная идея : также добавьте vc идентификатор запуска вашего приложения в качестве идентификатора (например, «LaunchVC»), чтобы вы могли его захватить и использовать его во время запуска. Это обеспечит беспрепятственный опыт для пользователя во время запуска и при выполнении задач запуска.

Вот как выглядит мой LaunchViewController

 @implementation LaunchViewController - (void)viewDidLoad { [super viewDidLoad]; // optional, but I really like this: // cover my view with my launch screen's view for a seamless start UIStoryboard *storyboard = [self.class storyboardWithKey:@"UILaunchStoryboardName"]; UINavigationController *vc = [storyboard instantiateViewControllerWithIdentifier:@"LaunchVC"]; [self.view addSubview:vc.view]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self hideBusyUI]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self showBusyUI]; // start your startup logic here: // let's say you need to do a network transaction... // [someNetworkCallingObject doSomeNetworkCallCompletion:^(id result, NSError *error) { if (/* some condition */) [self.class presentUI:@"AppUI"]; else if (/* some condition */) [self.class presentUI:@"LoginUI"]; // etc. }]; } #pragma mark - Busy UI // optional, but maybe you want a spinner or something while getting started - (void)showBusyUI { // in one app, I add a spinner on my launch storyboard vc // give it a tag, and give the logo image a tag, too // here in animation, I fade out the logo and fade in a spinner UIImageView *logo = (UIImageView *)[self.view viewWithTag:32]; UIActivityIndicatorView *aiv = (UIActivityIndicatorView *)[self.view viewWithTag:33]; [UIView animateWithDuration:0.5 animations:^{ logo.alpha = 0.0; aiv.alpha = 1.0; }]; } - (void)hideBusyUI { // an animation that reverses the showBusyUI } #pragma mark - Present UI + (void)presentUI:(NSString *)identifier { UIStoryboard *storyboard = [self storyboardWithKey:@"UIMainStoryboardFile"]; UINavigationController *vc = [storyboard instantiateViewControllerWithIdentifier:identifier]; UIWindow *window = [UIApplication sharedApplication].delegate.window; window.rootViewController = vc; // another bonus of this approach: any VC transition you like to // any of the app's main flows [UIView transitionWithView:window duration:0.3 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:nil]; } + (UIStoryboard *)storyboardWithKey:(NSString *)key { NSBundle *bundle = [NSBundle mainBundle]; NSString *storyboardName = [bundle objectForInfoDictionaryKey:key]; return [UIStoryboard storyboardWithName:storyboardName bundle:bundle]; } @end 

Первоначальный ответ ниже, хотя я предпочитаю свой нынешний подход

Давайте выражаем готовность приложения к запуску главного vc с булевым, что-то вроде:

 BOOL readyToRun = startupWorkIsDone && userIsLoggedIn; 
  1. Создайте AppStartupViewController и разместите его в раскадровке приложений.
  2. Не перетаскивайте его, и не делайте так, чтобы он смотрел vc, просто оставите его где-то плавающим.
  3. В инспекторе атрибутов vc в раскадровке установите его идентификатор как «AppStartupViewController».

В AppStartupViewController.m, когда условия readyToRun выполнены, он может отклонить себя:

 self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; // your choice here from UIModalTransitionStyle [self dismissViewControllerAnimated:YES completion:nil]; 

Теперь, когда приложение становится активным, оно может проверить готовность к запуску и представить AppStartupViewController, если это необходимо. В AppDelegate.h

 - (void)applicationDidBecomeActive:(UIApplication *)application { BOOL readyToRun = startupWorkIsDone && userIsLoggedIn; if (!readyToRun) { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; AppStartupViewController *startupVC = [storyboard instantiateViewControllerWithIdentifier:@"AppStartupViewController"]; [self.window.rootViewController presentViewController:startupVC animated:NO completion:nil]; // animate = NO because we don't want to see the mainVC's view } } 

В основном это ответ, но есть одна заминка. К сожалению, главный vc загружается (это нормально) и получает сообщение viewWillAppear: (не все), прежде чем будет представлен AppStartupViewController. Это означает, что в MainViewController.m необходимо добавить немного дополнительной логики запуска, например:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (readyToRun) { // the view will appear stuff i would have done unconditionally before } } 

Надеюсь, это полезно.

Другое решение при использовании навигационного контроллера.

  1. Ваш контроллер навигации является начальным контроллером представления, установите ваш основной контроллер в качестве корневого контроллера навигационного контроллера.

  2. Добавьте контроллер загрузки в раскадровку и свяжите его с именем segue стиля модального.

  3. В представлении вашего основного контроллераWillAppear запускает segue (только один раз для запуска приложения).

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if(_isFirstRun) { _isFirstRun = NO; [self performSegueWithIdentifier:@"segueLoading" sender:nil]; } } 

Это не сработает, если вы вызовите segue в viewDidLoad, вероятно, потому, что анимация контроллера навигации еще не завершена, и вы получите unbalanced calls to begin/end appearance transitions

  • iPhone, как получить текст UITextField при наборе текста?
  • Как загрузить файлы из UIWebView и снова открыть
  • OpenGL ES 2.0 / MonoTouch: текстура окрашена в красный цвет
  • Фильтрация UITableView из источника XML
  • Ошибка POSIX 12 («Невозможно выделить память») при загрузке файлов с iPhone
  • Как установить цвет аксессуаров UITableViewCell?
  • Исключение NSManagedObject «этот класс не соответствует требованиям кодирования ключа» и приводит к сбою приложения в ios 6, но работает для ios 5
  • Использование AppDelegate для обмена данными
  • Как программно добавить заголовок в UICollectionView с помощью UICollectionViewLayout
  • совместное использование кратных элементов с sharekit на facebook
  • Обновление приложения для iPhone в фоновом режиме
  • Interesting Posts

    Есть ли какой-либо частный api для функции «не беспокоить»?

    Динамические высоты ячейки UITableView корректны только после прокрутки

    Связывание графика Facebook в приложении iOS и веб-приложении

    Установка статических переменных в Objective C

    Удалить указанный файл из каталога документов

    Случайные сбои в приложении iOS App Google Tag Manager

    Как получить доступ к значениям текстового поля пользовательской ячейки Swift 3.0

    Перезагрузите представление UIPageViewController при изменении ориентации

    Производительность UILabel и CATextLayer

    Проводное подключение от iPhone до малины Pi

    Преобразовать временную метку UNIX в Data – iOS

    Каково имя этого элемента интерфейса? Указывает положение слайда / страницы

    добавление в UICollectionViewCell contentView через nib

    исключить subview из UITapGestureRecognizer

    Предотвращение UINavigationController от настройки источника, когда строка состояния скрыта в iOS 7

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.