Модальный экран входа в iOS отображается в любом месте приложения

Каков наилучший подход к созданию экрана входа в приложение iOS, который скользит (представляя его модально) всякий раз, когда пользователь не вошел в систему?

Пользователь будет «выведен из системы» в следующих случаях:

  • он никогда не заходил в приложение (т.е. впервые использовал)
  • он явно вышел из приложения
  • он вышел из системы на сервере (например, срок действия его токена безопасности на сервере истек, и это передается приложению)

Мое приложение состоит из UINavigationController, который установлен как RootViewController приложения, и каждый экран (кроме экрана входа в систему) помещается в NavigationController по мере того, как пользователь перемещается по приложению. Один из экранов, к которому пользователь может перейти (т. е. который помещается в стек), — это экран выхода (где пользователь может выйти из приложения). Экран входа в систему должен появляться модально, когда это необходимо, а логика и представление должны происходить из одного централизованного места. Я использую раскадровки.

Что я пробовал, так это создать подкласс UINavigationController (для RootViewController), и в его методе viewDidAppear я проверяю, вошел ли пользователь в систему (я сохраняю флаг в NSUserDefaults). Если он вошел в систему, первый экран приложения (программно) помещается в стек; если он не вошел в систему, экран входа в систему (программно) представлен модально.

Этот подход имеет следующие две проблемы:

  • вы не можете установить фоновое изображение для подкласса UINavigationController, поэтому на короткое время появляется пустой экран
  • viewDidAppear подкласса UINavigationController не вызывается при появлении в его RootViewController (особенно при выходе из экрана выхода из системы)

В идеале я хочу, чтобы одно центральное место проверяло, вошел ли пользователь в систему (я надеялся, что подклассовый метод UINavigationController будет этим местом), чтобы проверять состояние входа пользователя в систему и при необходимости отображать модальный экран входа в систему.

Я просмотрел экран входа в систему с помощью раскадровки и Пример экрана входа в систему, модально основанный на раскадровке (и другие, упомянутые в них), но ни один из них не решает проблему представление модального экрана входа в систему из центральной точки.


person mrtnkrstn    schedule 26.02.2014    source источник


Ответы (4)


Во-первых, вы должны отметить, что, согласно примечаниям разработчиков Apple, вы не должны создавать подкласс UINavigationController.

Во-вторых, это довольно основано на мнении, однако я предлагаю вам использовать класс делегата вашего приложения в качестве опорной точки для проверки статуса входа в систему, это одноэлемент, как UINavigationController, фактически.

person Woodstock    schedule 26.02.2014
comment
Как мне когда проверить статус входа в AppDelegate? Т.е. есть ли метод, который вызывается достаточно регулярно (например, viewDidAppear в ViewController), где я могу поставить галочку? - person mrtnkrstn; 27.02.2014

Я бы предложил опубликовать NSNotification, чтобы ваш AppDelegate мог слушать, чтобы AppDelegate взял на себя ответственность за представление вашего модального входа в систему.

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

person Mike Pollard    schedule 26.02.2014

Попробуйте модально представить UINavigationController из «Login ViewController»:

При запуске приложения отображается LoginVC, требующий учетных данных. Если вход выполнен успешно, нажмите UINavigationController.

Когда вход в систему становится недействительным (выход из системы, срок действия файла cookie истекает, 401 с сервера, ...), закройте UINavigationController и вернитесь в LoginVC.

Обратите внимание, что при возврате в LoginVC все состояние приложения теряется, что может быть, а может и не быть тем, что вам нужно.

Ваш AppDelegate должен сохранить ссылку на LoginVC, через которую вы можете вызвать «отклонить», например.

[((YourAppDelegate*)[[UIApplication sharedApplication] delegate]) fallbackToLoginVC]
person Hendrik Demmer    schedule 26.02.2014
comment
Это означает, что LoginViewController всегда будет находиться в стеке View Controller; разве это не плохо (особенно с точки зрения использования памяти)? - person mrtnkrstn; 27.02.2014

Итак, вот что я в итоге сделал:

Как указал Джон Вудс, не создайте подкласс UINavigationController. Вместо этого я создал базу UIViewController, которая в своей viewWillAppear проверяет, авторизован ли пользователь; если нет, модально представить экран входа в систему. Все контроллеры представлений, которым необходимо проверять состояние входа в систему, наследуются от этого базового контроллера представления, поэтому он становится «центральной точкой» для проверки состояния входа в систему (мне не нравится использовать AppDelegate для такой логики).

Мне нравится предложение Майка Полларда использовать уведомления для уведомления об истечении срока действия токена пользователя (поскольку это может произойти задолго до вызова viewWillAppear). Подписку на это уведомление также можно выполнить в базовом контроллере представления.

Решение Хендрика Деммера, вероятно, самое простое, но мне не нравится, когда экран входа в систему «скрывается» внизу стека контроллера представления — или это просто придирка?

person mrtnkrstn    schedule 27.02.2014