我已经在Stackoverflow上阅读了一些很好的问题/答案 . 但是我仍然在努力让这个工作起来 . 因此,经过4个小时的尝试,我不得不在同一主题上发布另一个问题 .

其他好的QAs:

How to correctly link different Auth accounts in Firebase IOS

Firebase authentication: linking multiple accounts in Swift

也试过按照firebase文档尝试失败:https://firebase.google.com/docs/auth/ios/account-linking

所以基本上我已经设法登录电子邮件和密码和Facebook工作(尚未谷歌) . 不过我的问题是链接这些帐户 .

我基本上创建了一个电子邮件和密码帐户 . 当尝试使用Facebook登录时,我收到的错误是已存在已发送电子邮件的用户 .

我理解这样的逻辑:

  • 用户选择提供商登录(例如Facebook)

  • 执行代码,直到收到提供者的凭据

  • 尝试将帐户与现有的电子邮件和密码帐户相关联,而不是像往常一样登录Firebase

  • (如果nr.3失败,请不要链接帐户,而是使用提供商凭据(例如Facebook)将用户登录到Firebase

  • (如果成功)返回已成功进行链接 .

下面是我对代码的实现......但它通过了一些错误 .

import UIKit
import Firebase
import FacebookCore
import FacebookLogin


class loginVC: UIViewController {

    @IBOutlet weak var emailField: UITextField!
    @IBOutlet weak var passwordField: UITextField!
    @IBOutlet weak var facebookBtn: UIButton!
    @IBOutlet weak var googleBtn: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // prepare the fields to be used - requires the exention at the bottom UITextFieldDelegate
        emailField.delegate = self
        passwordField.delegate = self
    }

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

        if Auth.auth().currentUser != nil {

            // if already logged in - send to feedVC
            self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)

        }
    }

    @IBAction func facebookBtnWasPressed(_ sender: Any) {
        FacebookLoginButtonClicked()

    }


    @IBAction func googleBtnWasPressed(_ sender: Any) {

    }


    @IBAction func loginBtnWasPressed(_ sender: Any) {
        if emailField.text != nil && passwordField.text != nil {

            AuthService.instance.loginUser(withEmail: emailField.text!, andPassword: passwordField.text!, loginComplete: { (success, loginError) in

                if success {
                    // if login is successful - send user to feedVC
                    self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)
//
                    print("Successfully logged in user")
                    //self.dismiss(animated: true, completion: nil)
                } else {
                        print(String(describing: loginError?.localizedDescription))
                }
            })
        }
    }

    @IBAction func iDontHaveAnAccountBtnWasPressed(_ sender: Any) {
        // Show signup view controller instead
        let signupVC = storyboard?.instantiateViewController(withIdentifier: "signupVC")
        present(signupVC!, animated: false, completion: nil)
    }

    @IBAction func forgottenMyPasswordBtnWasPressed(_ sender: Any) {


        Auth.auth().sendPasswordReset(withEmail: emailField.text!) { (error) in
            // ...
        }
    }


    @objc func FacebookLoginButtonClicked() {
        let loginManager = LoginManager()
        loginManager.logIn(readPermissions: [.publicProfile, .email, .userFriends], viewController: self) { loginResult in // request access to user's facebook details
            switch loginResult {
            case .failed(let error):
                print(error)
            case .cancelled:
                print("User cancelled login.")
            case .success(let grantedPermissions, let declinedPermissions, let accessToken):
                print(grantedPermissions)
                print(declinedPermissions)

                // Get Facebook credentials
                let credential = FacebookAuthProvider.credential(withAccessToken: (AccessToken.current?.authenticationToken)!)
                let FacebookAccessToken = accessToken

                // Check if existing user are already logged into Firebase
                let currentUser = Auth.auth().currentUser

                if currentUser != nil {
                    // Check if user already exists in Firebase, if true link accounts
                    Auth.auth().currentUser!.link(with: credential) {(user, error) in
                    if user != nil && error == nil {
                        // Linking accounts was a success
                        print("Linking of Facebook account with existing email and password successfull")
                    }

                    if let error = error {
                        print(error)
                        return
                    }
                }
                }

                else {

                    Auth.auth().signIn(with: credential) { (user, error) in
                        if let error = error {
                            print(error)
                            return
                        }
                        // User is signed in
                        // ...
                        print("User signed in with Firebase")
                    }
                }
                }
            }
        }
    }

extension loginVC: UITextFieldDelegate {

}

当Firebase中已存在电子邮件和密码帐户时,尝试使用Facebook登录时出错 .

Error Domain = FIRAuthErrorDomain Code = 17012“已存在具有相同电子邮件地址但登录凭据不同的帐户 . 请使用与此电子邮件地址关联的提供商登录 . ” UserInfo = {error_name = ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL,FIRAuthErrorUserInfoEmailKey = test @ gmail.com,NSLocalizedDescription =已存在具有相同电子邮件地址但登录凭据不同的帐户 . 使用与此电子邮件地址关联的提供商登录 . }