Swift/Firestore:完成不会被调用

Posted

技术标签:

【中文标题】Swift/Firestore:完成不会被调用【英文标题】:Swift/Firestore: Completion doesn't get called 【发布时间】:2020-10-31 19:16:16 【问题描述】:

我正在尝试在 Firestore 中创建一个“个人资料”集合,以便在我的用户上存储更多数据,而不仅仅是他们的电子邮件/姓名。 我坚持创建此文档并上传他们选择的个人资料图片(作为 URL)。

这是他们点击“注册”按钮时调用的函数:

func register() 
            Auth.auth().createUser(withEmail: self.email, password: self.pass)  (res, err) in
                if err != nil 
                    self.error = err!.localizedDescription
                    self.alert.toggle()
                    return
                
                // Success registering a new user
                guard let userUID = res?.user.uid else  return 

                uploadImageToFirestore(id: userUID, image: myImage) 
                    print("SUCCESS")
                    self.imageURL = downloadImageFromFirestore(id: userUID)
                    self.createUserDocument(id: userUID, imgURL: self.imageURL)
                
        

第一步是使用 uploadImageToFirestore 函数将图片上传到 Firebase 存储,我尝试使用完成处理程序在调用接下来的 2 个函数之前等待:

    func uploadImageToFirestore(id: String, image: UIImage, completion: () -> Void) 
    let storageRef = storage.reference().child("images/\(id)/image.jpg").putData(image.jpegData(compressionQuality: 0.35)!, metadata: nil)  (_, err) in
        if err != nil 
            print((err?.localizedDescription)!)
            return
        
        print("Success uploading picture to Firestore")
    

第二步是将新上传的图片下载到Firebase Storage上获取网址:

    func downloadImageFromFirestore(id: String) -> String 
    let storageRef = storage.reference().child("images/\(id)/image.jpg")
    storageRef.downloadURL  url, error in
        if error != nil 
            print("DEBUG: \((error?.localizedDescription)!)")
            return
        
        print("Success downloading picture from Firestore")
        self.imageURL = "\(url!)"
    
    return self.imageURL

第三步是在 Firestore 中使用 ImageURL 创建 Profile 集合:

    func createUserDocument(id: String, imgURL: String) 
    db.collection("profiles").document(id).setData([
        "name": name,
        "surname": surname,
        "email": email,
        "shelter": isMember == true ? shelters[selectedShelter] : shelters[0],
        "photoURL": imgURL,
        "reputation": 0,
        "uuid": id
    ])
     err in
        if let error = err 
            print("Error ading document: \(error)")
         else 
            print("New profile document created in Firestore")
        
    

问题

我面临的问题是,在我的“注册”函数中,uploadImageToFirestore 的完成块从未被调用,因此函数 createUserDocument 也没有。

这是实现我想要的最佳方式(也就是使用他们在注册时选择的图片的 imageURL 创建个人资料文档)吗?为什么我的完成块没有被调用? (我没有在控制台中看到“SUCCESS”)。

感谢您的帮助!

亲切的问候, 吉海斯

【问题讨论】:

您没有在uploadImageToFirestore 中调用完成处理程序。调用传递的闭包是你的责任。我还建议您定义完成处理程序以接受 Result 类型,以便您可以将成功或失败和错误传递给闭包 这听起来像是回答@Paulw11 的开始。 :) @Paulw11 答案非常好。我想补充三点;问题中的代码使用了许多回调并错过了一些错误处理,这可能会大大简化,因为下载网址在上传后直接可用。请参阅文档Upload from memory。 另外我注意到您正在使用 url self.imageURL = "\(url!)" 填充一个类 var,然后还 returning 从不需要的函数中返回 - 没有理由返回一些全班可用。更重要的是,return self.imageURL 将在 .downloadURL 函数作为其异步函数完成之前被调用,并且闭包之后的代码将在闭包中的代码之前执行(有时)。那么这个self.imageURL = downloadImageFromFirestore(id: userUID) 有点奇怪,因为它有时可能是一个空字符串。 这些都是好点。我没有看代码的其余代码,我只是看到了未调用完成处理程序的问题。 【参考方案1】:

您需要调用您传递给uploadImageToFirestore 的完成处理程序闭包。

您可能还应该传递error(如果有),以便您处理它。

func uploadImageToFirestore(id: String, image: UIImage, completion: (Error?) -> Void) 
    let storageRef = storage.reference().child("images/\(id)/image.jpg").putData(image.jpegData(compressionQuality: 0.35)!, metadata: nil)  (_, err) in
        completion(err)
    

【讨论】:

以上是关于Swift/Firestore:完成不会被调用的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的完成处理程序永远不会被调用?

WKWebview 导航响应方法在单击 webview 中的完成按钮时不会被调用

使用 Swift (Firestore) 访问特定文档字段

如何保护 QThread 函数,使其在完成之前的工作之前不会再次被调用?

Swift Firestore 更新字段值

Swift Firestore 删除嵌套在文档中的数组中的元素时出现问题