问候StackOverflow!
我真的是Swift开发的新手,所以请不要对我发疯:3
我已经为我的移动应用创建了登录页面(Firebase电子邮件+密码)
我已经实现了“自动登录”功能-因此,当用户首次登录时,该用户在关闭并打开应用程序后仍保持登录状态。
问题在于,每次用户打开应用程序时,viewDidLoad
和viewDidAppear
->之间会有微小的延迟-导致每次应用程序打开时,您都会看到登录屏幕大约需要0.4秒,直到它自动为用户唱歌为止。
用户登录后,用户将被隔离(无动画)到我的UITabBarController
。
我已经为我的LoginViewController
提供了代码。
LoginViewController是我的第一个应用加载控制器。
最诚挚的问候
class LoginViewController: UIViewController {
@IBOutlet weak var loginEmail: UITextField!
@IBOutlet weak var loginPassword: UITextField!
@IBOutlet weak var loginBorder: UIButton!
let userDefault = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
if userDefault.bool(forKey: "usersignedin") {
performSegue(withIdentifier: "login", sender: self)
}
//Border color button//
loginBorder.layer.borderColor = UIColor.white.cgColor
//Border color button//
//Hide Keyboard Use
self.hideKeyboardWhenTappedAround()
//Hide Keyboard Use
//start padding function for login
addPaddingAndBorder(to: loginEmail)
addPaddingAndBorder(to: loginPassword)
//start padding function for login
}
@IBAction func loginButton(_ sender: UIButton) {
Auth.auth().signIn(withEmail: loginEmail.text!, password: loginPassword.text!) { (user, error) in
if user != nil {
self.userDefault.set(true, forKey: "usersignedin")
self.userDefault.synchronize()
self.performSegue(withIdentifier: "login", sender: self)
} else {
let alert = UIAlertController(title: "Invalid Email or Password", message: nil, preferredStyle: .alert)
let okButton = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(okButton)
self.present(alert, animated: true, completion: nil)
}
}
}
}
答案 0 :(得分:4)
我们在当前项目中正在执行与此类似的操作,但是我们决定在AppDelegate
中首先显示哪个控制器。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
var storyboard: UIStoryboard!
if isLoggedIn {
storyboard = UIStoryboard(name: "main", bundle: nil)
}
else {
storyboard = UIStoryboard(name: "login", bundle: nil)
}
let viewController = storyboard.instantiateInitialViewController()!
viewController.loadViewIfNeeded()
window.rootViewController = viewController
}
这样做的好处是,在应用程序加载时,它立即将您带到正确的ViewController
,而不会首先短暂显示错误的内容。
答案 1 :(得分:1)
在情况为performSegue(withIdentifier:sender:)
的情况下,将对viewWillAppear(_:)
的呼叫移至viewDidAppear(_:)
而不是usersignedin = true
。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if userDefault.bool(forKey: "usersignedin") {
performSegue(withIdentifier: "login", sender: self)
}
}
此外,signIn
上未收到main thread
方法的响应。由于您没有更新UI
上的main thread
,因此会导致延迟。
在 UI
closure
方法的signIn
的{{1}}中的DispatchQueue.main.async
部分
Auth.auth().signIn(withEmail: loginEmail.text!, password: loginPassword.text!) { (user, error) in
if user != nil {
self.userDefault.set(true, forKey: "usersignedin")
self.userDefault.synchronize()
DispatchQueue.main.async { //here..........
self.performSegue(withIdentifier: "login", sender: self)
}
}
else {
let alert = UIAlertController(title: "Invalid Email or Password", message: nil, preferredStyle: .alert)
let okButton = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(okButton)
DispatchQueue.main.async { //here..........
self.present(alert, animated: true, completion: nil)
}
}
}
答案 2 :(得分:1)
这是正确的系统行为。 ViewDidLoad
的调用总是比ViewDidAppear
早得多。如果要基于userDefault.bool(forKey: "usersignedin")
更改基本视图控制器,则将该逻辑添加到设置主视图控制器的位置,并在已登录的情况下交换它们。
答案 3 :(得分:1)
更改视图控制器的顺序。始终首先加载UITabBarController
(作为初始控制器)。然后在您的UITabBarController
viewDidLoad
中,检查用户是否已登录。如果不是,则显示登录屏幕。这样,总是先加载UITabBarController
,然后根据自动登录条件显示登录屏幕。因此,当用户自动进入时,您的延迟问题就不会出现。
我已经在所有应用程序中使用了这个概念,并且效果很好。
答案 4 :(得分:1)
viewDidAppear(_:)
会在显示视图后立即发生。我建议将您的代码从viewDidAppear(_:)
移至viewWillAppear(_:)
。
您还可以在viewDidLoad()
中添加您的登录代码,因为甚至在viewWillAppear(_:)
之前也会调用此方法。
在您的情况下,您的代码将是:
override func viewDidLoad() {
super.viewDidLoad()
if userDefault.bool(forKey: "usersignedin") {
performSegue(withIdentifier: "login", sender: self)
}
}
在加载视图时,会以特定的顺序调用不同的方法:
viewDidLoad()
(仅在创建对象时一次。)viewWillAppear(_:)
viewDidAppear(_:)
当您将另一个视图控制器推入该视图控制器时,该视图控制器不会从视图控制器的堆栈中删除。重要的是,当您回到此视图控制器时,这次viewDidLoad()
不会被调用。因此只有这些方法按此顺序再次调用:
viewWillAppear(_:)
viewDidAppear(_:)
答案 5 :(得分:1)
最好的方法是根据登录状态决定在AppDelegate中加载哪个控制器
let navigationController = UINavigationController()
navigationController.navigationBar.barStyle = .black
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if UserDefaults.standard.object(forKey: "Token") != nil{
let initialViewController = storyboard.instantiateViewController(withIdentifier: "HomeViewController")
navigationController.viewControllers = [initialViewController]
} else{
let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
navigationController.viewControllers = [initialViewController]
}
navigationController.navigationBar.barTintColor = UIColor.black
navigationController.navigationBar.tintColor = UIColor.white
navigationController.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor : UIColor.white]
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()