只有在调用方法两次时,DispatchGroup才会退出

时间:2022-12-05 16:03:16

I'm trying to sign up users with Firebase auth. When a user signs up, I'd like them to be added to my Users collection in Firestore as well as the Users authorization section.

我正在尝试使用Firebase身份验证来注册用户。当用户注册时,我希望将它们添加到Firestore中的Users集合以及Users授权部分。

The createUser(withEmail: ...) method works every time. However, my db.collection("users").document(user.id).setData([..] method will only be called if I press the sign up button twice, and at that point the createUser(withEmail ...) method gets called again. Here's the relevant code

createUser(withEmail:...)方法每次都有效。但是,我的db.collection(“users”)。document(user.id).setData([..]方法只有在我按两次注册按钮时才会调用,此时createUser(withEmail ... )方法再次被调用。这是相关的代码

SignupViewController.swift

@IBAction func signupButtonTapped(_ sender: UIButton) {
    // user: User() defined here

    usersHelper.signup(user: user, password: password) { result in
        // This closure is only executed on the second press
        guard let user = result as? Firebase.User else {
            let error = result as? Error
            self.handleSignupError(error!)
            return
        }
        self.performSegue(withIdentifier: "ShowGroupsFromSignupSegue", sender: self)
    }
}

UsersHelper.Swift

func signup(user: User, password: String, completion: @escaping (_ result: Any?) -> Void) {
    let userDispatchGroup = DispatchGroup()
    var signupError: Error? = nil
    var dbError: Error? = nil
    var firebaseUser: Firebase.User? = nil

    userDispatchGroup.enter()
    usersDataModel.signupUser(user: user, password: password) { result in
        // Completion handler
        if result as? Error != nil {
            signupError = result as? Error
        } else {
            // Got the user
            firebaseUser = result as? Firebase.User
        }
        userDispatchGroup.leave()
    }

    userDispatchGroup.enter()
    usersDataModel.create(user: user) { err in
        // This will only execute if signUp is called twice
        if let result = err as? Error {
            print("Error msg: \(result.localizedDescription)")
            dbError = result
        }
        print("!Created db user")
        userDispatchGroup.leave()
    }

    userDispatchGroup.notify(queue: .main) {
        print("!dispatch group completed successfully")
        if (signupError == nil && dbError == nil) {
            completion(firebaseUser)
        } else {
            signupError != nil ? completion(signupError) : completion(dbError)
        }
    }
}

UsersDataModel.swift

func signupUser(user: User, password: String, _ completion: @escaping (_ err: Any? ) -> Void) {
    // Create user in Auth & create DB entry
    Auth.auth().createUser(withEmail: user.email, password: password) { (authResult, err) in
        if let err = err {
            print("Error creating user \(err)")
            completion(err)
        } else {
            print("User signed up successfully")
            completion(authResult) // completion called with User
        }
    }
}


func create(user: User, _ completion: @escaping (_ result: Any?) -> Void) {
    // userData dictionary created here

    db.collection("users").document(user.ID).setData(userData) { err in
        if let err = err {
            print("There was an error creating the user \(err)")
            completion(err)
        } else {
            print("!User created in db successfully!")
            completion(nil)
        }
    }
}

Any help is greatly appreciated! Thank you all in advance

任何帮助是极大的赞赏!谢谢大家

1 个解决方案

#1


0  

I've resolved the error. I ended up nesting the second network call in order to:

我已经解决了这个错误。我最终嵌套了第二个网络呼叫,以便:

  1. Get the uid from the firestore who was authenticated

    从经过身份验证的firestore获取uid

  2. Not break firestore rules about writing to the database w/o an authorized uid

    不要破坏关于使用授权的uid写入数据库的firestore规则

My UsersHelper.swift file now looks like

我的UsersHelper.swift文件现在看起来像

func signup(user: User, password: String, completion: @escaping (_ result: Any?) -> Void) {
    let userDispatchGroup = DispatchGroup()
    var signupError: Error? = nil
    var dbError: Error? = nil
    var firebaseUser: Firebase.User? = nil

    userDispatchGroup.enter()
    usersDataModel.signupUser(user: user, password: password) { result in
        // Completion handler
        if result as? Error != nil {
            // there was an error?
            print("Error: \(result)")
            signupError = result as? Error
        } else {
            // Got the user
            firebaseUser = result as? Firebase.User
            // Create user entry in DB
            user.ID = firebaseUser!.uid

            self.usersDataModel.create(user: user) { err in
                // Completion handler
                if let err = err as? Error {
                    dbError = err
                }
                userDispatchGroup.leave()
                print("Done")
            }
        }
    }

    userDispatchGroup.notify(queue: .main) {
        print("!dispatch group completed successfully")
        if (signupError == nil && dbError == nil) {
            completion(firebaseUser)
        } else {
            signupError != nil ? completion(signupError) : completion(dbError)
        }
    }
}

#1


0  

I've resolved the error. I ended up nesting the second network call in order to:

我已经解决了这个错误。我最终嵌套了第二个网络呼叫,以便:

  1. Get the uid from the firestore who was authenticated

    从经过身份验证的firestore获取uid

  2. Not break firestore rules about writing to the database w/o an authorized uid

    不要破坏关于使用授权的uid写入数据库的firestore规则

My UsersHelper.swift file now looks like

我的UsersHelper.swift文件现在看起来像

func signup(user: User, password: String, completion: @escaping (_ result: Any?) -> Void) {
    let userDispatchGroup = DispatchGroup()
    var signupError: Error? = nil
    var dbError: Error? = nil
    var firebaseUser: Firebase.User? = nil

    userDispatchGroup.enter()
    usersDataModel.signupUser(user: user, password: password) { result in
        // Completion handler
        if result as? Error != nil {
            // there was an error?
            print("Error: \(result)")
            signupError = result as? Error
        } else {
            // Got the user
            firebaseUser = result as? Firebase.User
            // Create user entry in DB
            user.ID = firebaseUser!.uid

            self.usersDataModel.create(user: user) { err in
                // Completion handler
                if let err = err as? Error {
                    dbError = err
                }
                userDispatchGroup.leave()
                print("Done")
            }
        }
    }

    userDispatchGroup.notify(queue: .main) {
        print("!dispatch group completed successfully")
        if (signupError == nil && dbError == nil) {
            completion(firebaseUser)
        } else {
            signupError != nil ? completion(signupError) : completion(dbError)
        }
    }
}