如何使用 Swift 解决 Firebase 中的异步问题?

How to beat asynchronous issues in Firebase with Swift?

所以我使用 imageURl 将图像发送到我的存储,但是当我尝试将该图像 URL post 到 FIRDataBase 时,它​​要么被放入为“”,要么当我设置一些条件逻辑以查看如果选择了图像,我必须执行两次第一次登录过程,谁能帮我解决这个问题,我相信 getUserNameAlert() 函数:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        if let image = info[UIImagePickerControllerEditedImage] as? UIImage{
            let imguid = NSUUID().uuidString
            let metadata = FIRStorageMetadata()
            metadata.contentType = "image/jpeg"

             var userImagesRef = DataService.ds.REF_USER_IMAGES.child(imguid).put(UIImageJPEGRepresentation(image, 0.2)!, metadata: metadata, completion: { (metadata, error) in
                if error != nil{
                    print("AA: able to upload image to FIREBASE STORAGE")
                }else{
                    print("GREAT SUCCESS FOR THE STORAGE")
                    imageSelected = true
                    let downloadURL = metadata?.downloadURL()?.absoluteString
                    if let url = downloadURL{
                        userImageURL = url
                    }
                }
             })

        }else{
            print("AA: Valid image wasn't selected")
        }
        imagePicker.dismiss(animated: true, completion: nil)

    }


 func getUserNameAlert(user:FIRUser, provider: String){

            let alert = UIAlertController(title: "Create a User Name", message: "Enter Your Desired User Name", preferredStyle: .alert)
            alert.addTextField { (textField) in
                textField.placeholder = "Enter User Name"
                alert.addAction(UIAlertAction(title: "Create", style: .default, handler: { (action) in
                    if let textFields = alert.textFields{
                        let theTextFields = textFields as! [UITextField]
                        userName = theTextFields[0].text!
                        self.present(self.imagePicker, animated: true, completion: nil)
                        if imageSelected == true{
                        self.completeSignIn(id: user.uid, userdata: ["provider":provider,"userName":userName,"imageURL":userImageURL])
                        }
                    }

                }))
                self.present(alert, animated: true, completion: nil)
            }
        }

并且 userNameURL 是一个字符串类型的全局变量

所以问题出在这些行中...

self.present(self.imagePicker, animated: true, completion:     
if imageSelected == true {
 self.completeSignIn(id: user.uid, userdata: ["provider":provider,"userName":userName,"imageURL":userImageURL])
}

问题是您的代码将调出 imagePicker,然后立即转到运行接下来的几行以查看 imageSelected ==真的。它不会等到用户完成图像选择器,这可能是您希望发生的事情。

您可以通过多种不同的方式解决此问题,具体取决于您希望获得的最佳用户体验。但这里有一些您可以尝试的策略:

策略一:移动completeSignIn以便在imagePickerController: didFinishPickingMedia...方法中调用它。当您成功上传图像后,当您有可用的 downloadURL 时,您会想要调用它。 (然后,为了完整起见,您还需要在 imagePickerController: didCancel 方法中调用它。)这会起作用,但缺点是您将无法调用 completeSignIn 直到图片已上传,在慢速网络上可能需要很长时间。

策略二: 运行 completeSignIn 就像你现在做的那样,但是当你'全部完成从上传方法中检索它。具体如何运作在很大程度上取决于您在 completeSignIn 通话中所做的事情。

这样做的好处是您不会再因等待用户上传巨幅图片而阻塞您的呼叫。然而,这对您来说意味着更多的工作,以确保您为正确的用户调整正确的 imageURL(尽管我猜您不会在您的应用程序中非常频繁地更换用户),并注意如果此上传调用在您未预期的时间完成,可能会出现其他奇怪的情况。