Ios VIEWDID显示延迟0.5秒

Ios VIEWDID显示延迟0.5秒,ios,swift,Ios,Swift,祝贺你 我对快速发展真的很陌生,所以请不要对我发疯:3 我已经为我的移动应用程序创建了登录页面(Firebase电子邮件+密码) 我已经实现了一个“自动登录”功能——因此,当用户第一次登录时,用户在关闭并打开应用程序后仍保持登录状态 问题是,每次用户打开应用程序时,viewDidLoad和viewDidAppear->之间都会有一点延迟,导致每次应用程序打开时,您都可以看到登录屏幕约0.4秒,直到它自动将用户签入 用户登录后,将用户分割(无动画)到myUITabBarController 我已经

祝贺你

我对快速发展真的很陌生,所以请不要对我发疯:3

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

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

问题是,每次用户打开应用程序时,
viewDidLoad
viewDidAppear
->之间都会有一点延迟,导致每次应用程序打开时,您都可以看到登录屏幕约0.4秒,直到它自动将用户签入

用户登录后,将用户分割(无动画)到my
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)              
            }
        }
    }
}

如果
usersignedin=true
,则将调用移动到
performsgue(标识符为:sender:)
viewwillbeen(:)
而不是
viewdidbeen(:)

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if userDefault.bool(forKey: "usersignedin") {
        performSegue(withIdentifier: "login", sender: self)
    }
}
另外,
主线程
上未接收到
signIn
方法的响应。由于您没有在
主线程上更新
UI
,这就是导致延迟的原因

signIn
方法的
closure
中的
UI
部分嵌入
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)
        }
    }
}

这是正确的系统行为
ViewDidLoad
总是比
ViewDidDisplay
更早被调用。如果要基于
userDefault.bool(forKey:“usersignedin”)
更改基本视图控制器,请将该逻辑添加到设置主视图控制器的位置,并在已登录时交换它们。

更改视图控制器的顺序。始终首先加载
UITabBarController
(作为初始控制器)。然后,在您的
UITabBarController
viewDidLoad
中,检查用户是否登录。如果没有,则显示登录屏幕。这样,始终首先加载
UITabBarController
,然后根据自动登录条件显示登录屏幕。因此,当用户自动输入时,您的延迟问题将不会出现

我在我所有的应用程序中都使用了这个概念,它工作得很好。

viewdideappear(:)
在视图出现后立即出现。我建议将您的代码从
viewdidispect(:)
移动到
viewwillispect(:)

您还可以在
viewdiload()
中添加登录代码,因为此方法甚至在
viewwillbeen(:)
出现之前就被调用了

在您的情况下,您的代码将是:

override func viewDidLoad(){
super.viewDidLoad()
if userDefault.bool(forKey:“usersignedin”){
性能检查(标识符为“登录”,发件人为自我)
}
}

更多信息: 加载视图时,会按特定顺序调用不同的方法:

  • viewDidLoad()
    (仅在创建对象时使用一次。)
  • 视图将出现(:)
  • [视图显示在屏幕上]
  • viewdide出现(:)
  • 将另一个视图控制器推到该视图控制器上时,该视图控制器不会从视图控制器堆栈中删除。重要的是,当您回到这个视图控制器时,这次不会调用
    viewDidLoad()
    。因此,只有这些方法会按以下顺序再次调用:

  • 视图将出现(:)
  • [视图显示在屏幕上]
  • viewdide出现(:)

  • 在我当前的项目中,我们正在做类似的事情,但是我们决定在
    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
    ,而不会首先短暂显示错误的控制器。

    最好的方法是根据登录状态在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()
    

    OP也应该这样做,但不是他问的。@Maximilian我看OP没有按照我的建议做。你好!谢谢你的回答!我的主视图控制器是LoginViewController tho。您的意思是我必须将userDefault.bool(forKey:“usersignedin”)移动到UITabBarController中吗?您可以将其移动到AppDelegate中,在窗口中设置
    rootViewController
    ,然后决定应首先显示哪个控制器。我看到另一个答案提到始终显示选项卡栏,然后在需要时在顶部显示登录,但我不喜欢这种方法,因为这意味着其中一个选项卡栏控制器必须知道如何显示登录。