others - IOS - viewDidAppear被延迟0.5秒

我创建了一个登录页面(Firebase Email Password )

问题是,每次打开应用程序时,viewDidLoad和viewDidAppear -

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) 


 }


 }


 }


}



时间:

我们在当前的项目中做了类似的,但是,我们决定先在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,不会首先显示错误。

这是正确的系统行为,总是比ViewDidAppear调用ViewDidLoad快很多,若要更改基础视图控制器,请执行下列操作: userDefault.bool(forKey:"usersignedin"),将该逻辑添加到你设置主视图控制器的位置,并在已登录时交换它们。

将调用移至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上没有收到,因为你没有更新main thread上的UI,所以,它会导致延迟。

UI部分嵌入DispatchQueue.main.asyncsignIn方法的closure


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)


 }


 }


}



viewDidAppear(_:)在视图出现后发生,我建议把你的代码从viewDidAppear(_:)转移到viewWillAppear(_:)

你还可以在viewDidLoad()中添加你的登录代码,因为在viewWillAppear(_:)之前调用此方法。

在你的情况下,你的代码为:


override func viewDidLoad() {


 super.viewDidLoad()



 if userDefault.bool(forKey:"usersignedin") {


 performSegue(withIdentifier:"login", sender: self)


 }


}



更多信息:

当加载视图时,不同的方法以特定顺序调用:

  • viewDidLoad() (仅在创建对象时),
  • viewWillAppear(_:)
  • [View appears on screen ]
  • viewDidAppear(_:)

在这一个视图控制器上,这个视图控制器将不会从视图控制器堆栈中删除,重要的是,当你回到这个视图控制器时,这次viewDidLoad()将不会被调用,因此,只有这些方法才能按以下顺序再次调用:

  • viewWillAppear(_:)
  • [View appears on screen ]
  • viewDidAppear(_:)

最好的方法是在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()



...