Я создаю приложение для iOS, используя раскадровку. Корневым контроллером представления является контроллер панели вкладок. Я создаю процесс входа / выхода, и он в основном работает нормально, но у меня есть несколько проблем. Мне нужно знать ЛУЧШИЙ способ настроить все это.
Я хочу сделать следующее:
- Показать экран входа в систему при первом запуске приложения. Когда они войдут, перейдите на первую вкладку контроллера панели вкладок.
- Каждый раз, когда они запускают приложение после этого, проверьте, вошли ли они в систему, и сразу перейдите к первой вкладке корневого контроллера панели вкладок.
- Когда они вручную нажимают кнопку выхода из системы, показывают экран входа в систему и очищают все данные от контроллеров представления.
До сих пор я устанавливал корневой контроллер представления на контроллер панели вкладок и создавал собственный переход к моему контроллеру представления входа в систему. Внутри моего класса Tab Bar Controller я проверяю, вошли ли они внутрь viewDidAppear
метода, и выполняю следующую последовательность действий:[self performSegueWithIdentifier:@"pushLogin" sender:self];
Я также настраиваю уведомление о том, когда необходимо выполнить действие выхода из системы: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutAccount) name:@"logoutAccount" object:nil];
После выхода из системы я очищаю учетные данные из цепочки для ключей, запускаю [self setSelectedIndex:0]
и выполняю процедуру, чтобы снова показать контроллер вида входа в систему.
Все это прекрасно работает, но мне интересно: должна ли эта логика быть в AppDelegate?У меня также есть две проблемы:
- Первый раз, когда они запускают приложение , контроллер панели вкладок кратко показывает перед выполнением перехода. Я пытался переместить код в,
viewWillAppear
но переход не будет работать так рано. - Когда они выходят из системы, все данные все еще находятся внутри всех контроллеров представления. Если они входят в новую учетную запись, данные старой учетной записи все еще отображаются, пока они не обновятся.Мне нужен способ, чтобы очистить это легко при выходе из системы.
Я открыт для переделки этого. Я подумал о том, чтобы сделать экран входа в систему корневым контроллером представления или создать контроллер навигации в AppDelegate для обработки всего ... Я просто не уверен, какой метод на данный момент лучший.
Ответы:
В вашем appDelegate.m внутри вашего didFinishLaunchingWithOptions
В файле SignUpViewController.m
В файле MyTabThreeViewController.m
Версия Swift 4
didFinishLaunchingWithOptions в делегате приложения, предполагая, что ваш начальный контроллер представления является подписанным в TabbarController.
В контроллере регистрации:
MyTabThreeViewController
источник
AppDelegate
внутриUIViewController
и установкиwindow.rootViewController
там. Я не считаю это «лучшей практикой».-1
без публикации ответа: stackoverflow.com/a/30664935/1226304AppDelegate
внутреннейUIViewController
-1 для хранения ключа входа вNSUserDefaults
. Это очень-очень небезопасно для такого рода данных!Вот что я в итоге сделал, чтобы достичь всего. Единственное, что вам нужно учитывать в дополнение к этому, это (а) процесс входа в систему и (б) где вы храните данные своего приложения (в данном случае я использовал синглтон).
Как вы можете видеть, контроллер корневого представления - это мой контроллер основной вкладки . Я сделал это, потому что после того, как пользователь вошел в систему, я хочу, чтобы приложение запускалось непосредственно на первой вкладке. (Это позволяет избежать «мерцания», когда временно отображается вид входа в систему.)
AppDelegate.m
В этом файле я проверяю, вошел ли пользователь уже в систему. Если нет, я нажимаю контроллер вида входа в систему. Я также управляю процессом выхода из системы, где я очищаю данные и показываю представление входа в систему.
LoginViewController.m
Здесь, если вход успешен, я просто отклоняю представление и отправляю уведомление.
источник
[self.window makeKeyAndVisible]; [self.window.rootViewController presentViewController:viewController animated:animated completion:nil];
с ,self.window.rootViewController = viewController;
чтобы предотвратить мерцание. Чтобы оживить это, просто оберните это в[UIView transitionWithView...];
РЕДАКТИРОВАТЬ: Добавить действие выхода из системы.
1. Прежде всего подготовьте файл делегата приложения
AppDelegate.h
AppDelegate.m
2. Создайте класс с именем User.
user.h
User.m
3. Создайте новый контроллер RootViewController и соедините с первым видом, где живут кнопки входа. Добавьте также идентификатор раскадровки: «initialView».
RootViewController.h
RootViewController.m
4. Создайте новый контроллер LoginViewController и подключитесь к представлению входа в систему.
LoginViewController.h
LoginViewController.m
5. В конце добавьте новый контроллер ProfileViewController и подключите его к представлению профиля во вкладке ViewViewController.
ProfileViewController.h
ProfileViewController.m
LoginExample - это пример проекта для дополнительной помощи.
источник
Мне не понравился ответ Бхавьи из-за использования
AppDelegate
внутри View Controllers и настройкиrootViewController
не имеет анимации. И у ответа Тревора есть проблема с мигающим контроллером представления на iOS8.UPD 18.07.2015
AppDelegate внутри View Controllers:
Изменение состояния (свойств) AppDelegate внутри контроллера представления нарушает инкапсуляцию.
Очень простая иерархия объектов в каждом проекте iOS:
AppDelegate (владеет
window
иrootViewController
)ViewController (владеет
view
)Это нормально, что объекты сверху меняют объекты снизу, потому что они их создают. Но это не нормально, если объекты в нижней части изменяют объекты поверх них (я описал некоторый базовый принцип программирования / ООП: DIP (Принцип инверсии зависимости: модуль высокого уровня не должен зависеть от модуля низкого уровня, но они должны зависеть от абстракций) ).
Если какой-либо объект изменит какой-либо объект в этой иерархии, рано или поздно в коде будет беспорядок. Это может быть хорошо на небольших проектах, но не интересно копаться в этом беспорядке на битовых проектах =]
UPD 18.07.2015
Я копирую анимацию модального контроллера, используя
UINavigationController
(tl; dr: check the project ).Я использую,
UINavigationController
чтобы представить все контроллеры в моем приложении. Изначально я отображал контроллер вида входа в стек навигации с простой анимацией push / pop. Затем я решил изменить его на модальный с минимальными изменениями.Как это устроено:
Начальный контроллер представления (или
self.window.rootViewController
) - UINavigationController с ProgressViewController какrootViewController
. Я показываю ProgressViewController, потому что DataModel может занять некоторое время для инициализации, потому что он встраивает основной стек данных, как в этой статье (мне действительно нравится этот подход).AppDelegate отвечает за получение обновлений статуса входа в систему.
DataModel обрабатывает вход / выход пользователя, а AppDelegate наблюдает за его
userLoggedIn
свойством через KVO. Возможно, не лучший способ сделать это, но он работает для меня. (Почему KVO плохо, вы можете проверить в этой или этой статье (Почему не использовать уведомления? Часть).ModalDismissAnimator и ModalPresentAnimator используются для настройки push-анимации по умолчанию.
Как работает логика аниматоров:
AppDelegate устанавливает себя как делегат
self.window.rootViewController
(который является UINavigationController).AppDelegate возвращает одного из аниматоров в
-[AppDelegate navigationController:animationControllerForOperation:fromViewController:toViewController:]
случае необходимости.Аниматоры реализуют
-transitionDuration:
и-animateTransition:
методы.-[ModalPresentAnimator animateTransition:]
:Тестовый проект здесь .
источник
AppDelegate
(мне было бы интересно понять, почему вы это делаете), но ваш комментарий об отсутствии анимации очень верный. Это можно решить с помощью этого ответа: stackoverflow.com/questions/8053832/…UITabBarController
. Я бы, вероятно, начал с оконного подхода вместо манипулирования контроллерами представления.Вот мое решение Swifty для любых будущих зрителей.
1) Создайте протокол для обработки функций входа и выхода:
2) Расширить указанный протокол и предоставить здесь функциональность для выхода из системы:
3) Затем я могу согласовать свой AppDelegate с протоколом LoginFlowHandler и вызвать
handleLogin
при запуске:Отсюда мое расширение протокола будет обрабатывать логику или определять, будет ли пользователь входить / выходить, а затем соответствующим образом изменять окна rootViewController!
источник
LoginFlowHandler
. Я что-то упускаю? Кроме того, я предполагаю, что этот код управляет входом только при запуске. Как мне управлять выходом из контроллера вида?AppState
Следовательно, эта реализация будет зависеть от того, как вы сохраняете свои пользовательские данные на диск.handleLogout
функциональность?LoginFlowHandler
протоколом. После этого вы получите возможность вызова метода handleLogout. Смотрите мой шаг 3 для примера того, как я это сделал для класса AppDelegate.Делать это из приложения делегата НЕ рекомендуется. AppDelegate управляет жизненным циклом приложения, связанным с запуском, приостановкой, завершением и т. Д. Я предлагаю сделать это с вашего начального контроллера просмотра в
viewDidAppear
. Можноself.presentViewController
иself.dismissViewController
из логина просмотра контроллера. Сохранитеbool
ключ,NSUserDefaults
чтобы увидеть, запускается ли он впервые.источник
После создания LoginViewController и TabBarController нам нужно добавить StoryboardID как « loginViewController » и « tabBarController » соответственно.
Тогда я предпочитаю создать структуру Constant :
В LoginViewController добавьте IBAction :
В ProfileViewController добавьте IBAction :
В AppDelegate добавьте строку кода в didFinishLaunchingWithOptions :
Наконец, создайте класс Switcher :
Вот и все!
источник
В Xcode 7 вы можете иметь несколько storyBoards. Будет лучше, если вы сможете сохранить поток входа в систему в отдельной раскадровке.
Это можно сделать с помощью SELECT VIEWCONTROLLER> Editor> Refactor to Storyboard
А вот версия Swift для установки представления как RootViewContoller-
источник
Я использую это для проверки первого запуска:
(если пользователь удаляет приложение и переустанавливает его, это считается первым запуском)
В AppDelegate я проверяю первый запуск и создаю навигационный контроллер с экранами входа в систему (логин и регистрация), которые я помещаю поверх текущего главного окна:
Так как он находится поверх обычного контроллера представления, он не зависит от остальной части вашего приложения, и вы можете просто отключить контроллер представления, если он вам больше не нужен. И вы также можете представить представление таким образом, если пользователь нажимает кнопку вручную.
Кстати: я сохраняю данные для входа от моих пользователей, как это:
Для выхода: я переключился с CoreData (слишком медленно) и теперь использую NSArrays и NSDictionaries для управления своими данными. Выход из системы означает просто очистить эти массивы и словари. Плюс я обязательно установлю свои данные в viewWillAppear.
Вот и все.
источник
Я нахожусь в той же ситуации, что и вы, и решение, которое я нашел для очистки данных, заключается в удалении всего содержимого CoreData, на которое полагаются мои контроллеры представления для получения информации. Но я все же нашел этот подход очень плохим, я думаю, что более элегантный способ сделать это может быть реализован без раскадровок и использования только кода для управления переходами между контроллерами представления.
Я нашел этот проект на Github, который делает все это только по коду, и его довольно легко понять. Они используют боковое меню в стиле Facebook, и они меняют контроллер центрального вида в зависимости от того, вошел ли пользователь в систему или нет. Когда пользователь выходит из системы, он
appDelegate
удаляет данные из CoreData и снова устанавливает контроллер основного вида на экран входа в систему.источник
У меня была похожая проблема для решения в приложении, и я использовал следующий метод. Я не использовал уведомления для обработки навигации.
У меня есть три раскадровки в приложении.
Моя первоначальная раскадровка в приложении - раскадровка экрана-заставки. У меня есть навигационный контроллер в качестве корня раскадровки для входа в систему и панели вкладок для управления навигацией контроллера представления.
Я создал класс Navigator для обработки навигации в приложении, и он выглядит так:
Давайте посмотрим на возможные сценарии:
Поскольку у меня в качестве корневого контроллера навигации, я создаю экземпляр контроллера навигации в качестве начального контроллера представления.
Это удаляет раскадровку slpash из корня окна приложения и заменяет ее раскадровкой входа в систему.
Из раскадровки входа в систему, когда пользователь успешно вошел в систему, я сохраняю данные пользователя в User Defaults и инициализирую синглтон UserData для доступа к данным пользователя. Затем раскадровка панели вкладок загружается с помощью метода навигатора.
Теперь пользователь выходит из экрана настроек в панели вкладок. Я очищаю все сохраненные пользовательские данные и перехожу к экрану входа.
Когда пользователь запускает приложение, загружается заставка. Я проверяю, вошел ли пользователь в систему, и получаю доступ к данным пользователя из настроек пользователя по умолчанию. Затем инициализируйте синглтон UserData и показывает панель вкладок вместо экрана входа в систему.
источник
Спасибо бхавья за решение. Было два ответа о Свифте, но они не очень целы. Я сделал это в swift3. Ниже приведен основной код.
В AppDelegate.swift
В SignUpViewController.swift
В функции logOutAction
источник
введите описание изображения здесь
В приложении Delegate.m
}
view controller.m В виду сделал загрузку
}
В действии кнопки выхода
источник
NSUserDefaults
очень-очень небезопасно для такого рода данных!