用邮件写完登录后,我将社交登录集成到我的应用程序中,并从Google登录开始。现在,它会在应用启动时自动登录,而不是在我按Google登录按钮时登录。如果我在弹出窗口中取消它,则会在AppDelegate`的令牌行上抛出Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
。同样注销也不会阻止再次自动登录。
遵循Firebase手册中有关Google登录的说明,这非常令人困惑,所以我确定犯了一些明显的错误。
这是到目前为止的代码:
AppDelegate:
// start google sign in methods
@available(iOS 9.0, *)
func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any])
-> Bool {
return GIDSignIn.sharedInstance().handle(url,
sourceApplication:options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String,
annotation: options[UIApplicationOpenURLOptionsKey.annotation])
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
// ...
print("User successfully signed in with Google",user)
guard let idToken = user.authentication.idToken else {
return
}
guard let accessToken = user.authentication.accessToken else {return}
let credentials = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: accessToken)
Auth.auth().signInAndRetrieveData(with: credentials) { (user, error) in
if let error = error {
print("Failed to create user with Google account", error)
return
}
print("Succesfully created new user in Firebase with Google account")
}
if let error = error {
// ...
print("User failed to sign in with Google", error)
return
}
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
accessToken: authentication.accessToken)
// let storyboard = UIStoryboard(name: "Main", bundle: nil)
// var mainVC = self.window?.visibleViewController as? MainNavigationController
// mainVC = storyboard.instantiateViewController(withIdentifier: "MainNavigationController") as? MainNavigationController
}
func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
// Perform any operations when the user disconnects from app here.
// ...
}
// end of google sign in
Google登录应该对主菜单执行搜索,但不能。 仅在第一次登录时,它便会到达所需的vc。
这是Login类:
import UIKit
import Firebase
import GoogleSignIn
class LoginViewController: UIViewController, GIDSignInUIDelegate {
// outlets
@IBOutlet weak var backGroundImage: UIImageView!
@IBOutlet weak var userNameTextField: UITextField!
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
@IBOutlet weak var confirmPasswordTextField: UITextField!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if Auth.auth().currentUser != nil {
self.performSegue(withIdentifier: "skipSegue", sender: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
setGoogleButton()
setFacebookButton()
}
// dismiss keyboard on touch outside textfields
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for txt in self.view.subviews {
if txt.isKind(of: UITextField.self) && txt.isFirstResponder {
txt.resignFirstResponder()
}
}
}
private func setGoogleButton() {
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().signIn()
}
private func setFacebookButton() {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Actions
@IBAction func newUserRegisterButton(_ sender: Any) {
if passwordTextField.text != confirmPasswordTextField.text{
let alertController = UIAlertController(title: "Password Incorrect", message: "Please re-type password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
else{
Auth.auth().createUser(withEmail: emailTextField.text!, password: passwordTextField.text!){ (user, error) in
if error == nil {
self.performSegue(withIdentifier: "skipSegue", sender: self)
}
else{
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
@IBAction func mailLogin(_ sender: UIButton) {
Auth.auth().signIn(withEmail: emailTextField.text!, password: passwordTextField.text!) { (user, error) in
if error == nil{
self.performSegue(withIdentifier: "skipSegue", sender: self)
}
else{
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
@IBAction func facebookLogin(_ sender: UIButton) {
}
@IBOutlet weak var signInButton: GIDSignInButton!
@IBAction func googleSignInButton(_ sender: GIDSignInButton) {
performSegue(withIdentifier: "skipSegue", sender: self)
}
@IBAction func logoutButton(_ sender: UIButton) {
}
@IBAction func skipButton(_ sender: UIButton) {
performSegue(withIdentifier: "skipSegue", sender: self)
}
}
退出:
@IBAction func logOutButton(_ sender: UIButton) {
// firebase auth sign out
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
} catch let signOutError as NSError {
print ("Error signing out: %@", signOutError)
}
// GSI log out
GIDSignIn.sharedInstance().signOut()
print("User successfully logged out Firebase with Google account")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initial = storyboard.instantiateInitialViewController()
UIApplication.shared.keyWindow?.rootViewController = initial
}
func signOutOverride() {
do {
GIDSignIn.sharedInstance().signOut()
try GIDSignIn.sharedInstance()?.disconnect()
// Set the view to the login screen after signing out
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initial = storyboard.instantiateInitialViewController()
UIApplication.shared.keyWindow?.rootViewController = initial
// let storyboard = UIStoryboard(name: "SignIn", bundle: nil)
// let loginVC = storyboard.instantiateViewControllerWithIdentifier("SignInVC") as! SignInViewController
// let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
// appDelegate.window?.rootViewController = loginVC
} catch let signOutError as NSError {
print ("Error signing out: \(signOutError)")
}
}
我阅读了许多有关吊销令牌并使用户与应用断开连接的帖子,但是无法实现这些解决方案,因为某些解决方案在obj-c中使用,而另一些在较早的swift语法中使用。 有和我一样的问题吗? 像往常一样感谢。
答案 0 :(得分:1)
经过多次尝试和错误,由于Google提供了讽刺的有用文档,我才发现问题出在哪里。他们建议将标志放在viewDidLoad()' and that obviously get's called every time the VC gets instantiated. I so Moved into the Google sign in button and left the delegate only in
viewDidLoad()中
现在一切都按预期工作。
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().uiDelegate = self
setFacebookButton()
}
@IBOutlet weak var signInButton: GIDSignInButton!
@IBAction func googleSignInButton(_ sender: GIDSignInButton) {
GIDSignIn.sharedInstance()?.signIn()
performSegue(withIdentifier: "skipSegue", sender: self)
}