如何使用 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(尽管我猜您不会在您的应用程序中非常频繁地更换用户),并注意如果此上传调用在您未预期的时间完成,可能会出现其他奇怪的情况。
所以我使用 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(尽管我猜您不会在您的应用程序中非常频繁地更换用户),并注意如果此上传调用在您未预期的时间完成,可能会出现其他奇怪的情况。