viewDidAppear延迟了0.5秒

时间:2019-06-12 09:31:43

标签: ios swift

问候StackOverflow!

我真的是Swift开发的新手,所以请不要对我发疯:3

我已经为我的移动应用创建了登录页面(Firebase电子邮件+密码)

我已经实现了“自动登录”功能-因此,当用户首次登录时,该用户在关闭并打开应用程序后仍保持登录状态。

问题在于,每次用户打开应用程序时,viewDidLoadviewDidAppear->之间会有微小的延迟-导致每次应用程序打开时,您都会看到登录屏幕大约需要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)              
            }
        }
    }
}

6 个答案:

答案 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)
    }
}

更多信息:

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

  1. viewDidLoad()(仅在创建对象时一次。)
  2. viewWillAppear(_:)
  3. [视图出现在屏幕上]
  4. viewDidAppear(_:)

当您将另一个视图控制器推入该视图控制器时,该视图控制器不会从视图控制器的堆栈中删除。重要的是,当您回到此视图控制器时,这次viewDidLoad()不会被调用。因此只有这些方法按此顺序再次调用:

  1. viewWillAppear(_:)
  2. [视图出现在屏幕上]
  3. 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()