【问题标题】:DispatchGroup will only exit when method is called twiceDispatchGroup 只会在方法被调用两次时退出
【发布时间】:2018-10-31 17:03:15
【问题描述】:

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

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? 的闭包不是很好。你的闭包应该接受一个成功和一个可选的Error 参数,就像Auth.auth() 一样。
  • create 中的功能是否需要经过身份验证的用户,而您第一次调用它时没有?
  • @Paulw11 我不这么认为 - 我的 Firestore 规则设置为允许所有人写入。但是当我只从Auth.auth() 的完成闭包中调用create() 时,这些调用确实有效。我只是不想有这样的嵌套网络调用

标签: ios swift firebase asynchronous closures


【解决方案1】:

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

  1. 从经过身份验证的 Firestore 中获取 uid

  2. 不违反关于在没有授权 uid 的情况下写入数据库的 Firestore 规则

我的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)
        }
    }
}

【讨论】:

    猜你喜欢
    • 2021-12-17
    • 1970-01-01
    • 2021-11-04
    • 2023-03-16
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    相关资源
    最近更新 更多