How do I switch to a different view controller from the App Delegate?

末鹿安然 提交于 2021-01-29 20:22:16

问题


Once the user signs in with Google, I want to take them to the home screen; however, the code does not fully execute this.

This is the code:

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
              withError error: Error!) {
      if let error = error {
        if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue {
          print("The user has not signed in before or they have since signed out.")
        } else {
          print("\(error.localizedDescription)")
        }
        return
      }
        let firstName = user.profile.givenName
        let lastName = user.profile.familyName
        let email = user.profile.email
    //Firebase sign in
      guard let authentication = user.authentication else {return}
        let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken, accessToken: authentication.accessToken)

        Auth.auth().signIn(with: credential) { (authResult, error) in
            if let error = error {
                print("Firebase sign In error")
                print(error)
                return
            } else {
                let db = Firestore.firestore()

                db.collection("users").addDocument(data: ["firstName": firstName!, "lastName": lastName!, "email": email!, "uid": authResult!.user.uid]) { (error) in

                    if error != nil {
                        print("Error: User data not saved")
                    }
            }
            print("User is signed in with Firebase")
            let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let homeViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeVC") as! HomeViewController
            self.window?.rootViewController = homeViewController
            self.window?.makeKeyAndVisible()

        }
    }
}

More specifically:

Auth.auth().signIn(with: credential) { (authResult, error) in
            if let error = error {
                print("Firebase sign In error")
                print(error)
                return
            } else {
                let db = Firestore.firestore()

                db.collection("users").addDocument(data: ["firstName": firstName!, "lastName": lastName!, "email": email!, "uid": authResult!.user.uid]) { (error) in

                    if error != nil {
                        print("Error: User data not saved")
                    }
            }
            print("User is signed in with Firebase")
            let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let homeViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeVC") as! HomeViewController
            self.window?.rootViewController = homeViewController
            self.window?.makeKeyAndVisible()

        }
    }

the print("User is signed in with Firebase") does take place but it fails to switch the HomeViewController and I'm not sure what it is that I am doing wrong here.


回答1:


The problem in the code is that Firebase is asynchronous. So this section

} else {
   let db = Firestore.firestore()

   db.collection("users").addDocument(data: ["firstName": firstName!, "lastName": lastName!, "email": email!, "uid": authResult!.user.uid]) { (error) in

      if error != nil {
         print("Error: User data not saved")
      }
   }

   print("User is signed in with Firebase")

This print statement

print("User is signed in with Firebase")

will execute before the code within the closure. The reason is the code is faster than the internet - you have to 'wait' for data to be returned from Firebase before moving forward in your code. To fix, move the statements inside the closure so they execute when Firebase returns

} else {
   let db = Firestore.firestore()

   db.collection("users").addDocument(data: ["firstName": firstName!, "lastName": lastName!, "email": email!, "uid": authResult!.user.uid]) { (error) in

      if error != nil {
         print("Error: User data not saved")
         return
      }

      print("User is signed in with Firebase")
      let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
      let homeViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeVC") as! HomeViewController
      self.window?.rootViewController = homeViewController
      self.window?.makeKeyAndVisible()
    }

Note that with this code flow, every time an existing user signs it, it will create a new document in the users collection. That's probably not the intention.




回答2:


My guess is that window is nil and that's why your code isn't executing properly. Try the code below if you are targeting iOS 13. Ideally, you would want to move the Sign-in code inside SceneDelegate and duplicate it in AppDelegate if your app also supports iOS 12, 11 etc.

   Auth.auth().signIn(with: credential) { (authResult, error) in
        if let error = error {
            print("Firebase sign In error")
            print(error)
            return
        } else {
            let db = Firestore.firestore()

            db.collection("users").addDocument(data: ["firstName": firstName!, "lastName": lastName!, "email": email!, "uid": authResult!.user.uid]) { (error) in

                if error != nil {
                    print("Error: User data not saved")
                }
            }
            print("User is signed in with Firebase")
            DispatchQueue.main.async {
                let scene = UIApplication.shared.connectedScenes.first
                if let sceneDelegate = scene?.delegate as? SceneDelegate {  
                    let window = sceneDelegate?.window
                    let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                    let homeViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeVC") as! HomeViewController
                    window?.rootViewController = homeViewController
                    window?.makeKeyAndVisible()

                }
            }
        }
    }


来源:https://stackoverflow.com/questions/62354073/how-do-i-switch-to-a-different-view-controller-from-the-app-delegate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!