SWIFT IOS:并非所有数据都保存到Firebase

时间:2018-11-28 21:07:48

标签: ios swift firebase firebase-realtime-database

我有以下代码,我正在尝试将数据保存到Firebase。保存是非常随机的。有时只有第一个.setValue被发布到firebase。有时前两个,有时前三个。它似乎从来没有超过三个。这仅在我添加.putData方法保存图像时才开始发生。如果我注释掉“保存照片”部分,则效果很好。有任何想法吗?顺便说一句,我只是添加了调度队列,看它是否可以解决问题。没有。

private func saveEvents() {

    // Createe a database reference
    databaseRef = Database.database().reference()

    for event in events {
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            guard let self = self else {
                return
            }
            let fireKey = event.eventName.trimmingCharacters(in: .whitespaces) + " " + event.eventCity.trimmingCharacters(in: .whitespaces)

            self.databaseRef?.child("Event").child(fireKey)
            self.databaseRef?.child("Event").child(fireKey).child("eventCategory").setValue(event.eventCategory)
            self.databaseRef?.child("Event").child(fireKey).child("eventCity").setValue(event.eventCity)
            self.databaseRef?.child("Event").child(fireKey).child("eventContact").setValue(event.eventContact)
            self.databaseRef?.child("Event").child(fireKey).child("eventCreator").setValue(event.eventCreator)
            self.databaseRef?.child("Event").child(fireKey).child("frequency").setValue(event.frequency)
            self.databaseRef?.child("Event").child(fireKey).child("eventDate").setValue(event.eventDate)
            self.databaseRef?.child("Event").child(fireKey).child("eventToDate").setValue(event.eventToDate)
            self.databaseRef?.child("Event").child(fireKey).child("eventEmail").setValue(event.eventEmail)
            self.databaseRef?.child("Event").child(fireKey).child("eventWebSite").setValue(event.eventWebSite)
            self.databaseRef?.child("Event").child(fireKey).child("eventName").setValue(event.eventName)
            self.databaseRef?.child("Event").child(fireKey).child("eventPhone").setValue(event.eventPhone)
            self.databaseRef?.child("Event").child(fireKey).child("eventState").setValue(event.eventState)
            self.databaseRef?.child("Event").child(fireKey).child("eventCountry").setValue(event.eventCountry)
            self.databaseRef?.child("Event").child(fireKey).child("eventStreet").setValue(event.eventStreet)
            for review in event.eventReviews {
                let commentKey = event.eventName + " " + review.vendorName
                self.databaseRef?.child("Event").child(fireKey).child("Reviews")
                self.databaseRef?.child("Event").child(fireKey).child("Reviews").child(commentKey)
                self.databaseRef?.child("Event").child(fireKey).child("Reviews").child(commentKey).child("Comment").setValue(review.vendorComment)
                self.databaseRef?.child("Event").child(fireKey).child("Reviews").child(commentKey).child("Rating").setValue(review.vendorRating)
                self.databaseRef?.child("Event").child(fireKey).child("Reviews").child(commentKey).child("Reviewer").setValue(review.vendorName)
            }

            //check if there is only a Default image before storing in firebase
            if event.eventImage != UIImage(named: "UploadPhoto") {
                DispatchQueue.main.async { [weak self] in
                    let imageRef = self!.databaseRef.child("Event").child(fireKey).child("images").childByAutoId()
                    let imageStorageKey = imageRef.key
                    if let imageData = UIImageJPEGRepresentation(event.eventImage, 0.6) {
                        let imageStorageRef = self!.storageRef.child("images").child(imageStorageKey!)
                        let uploadTask = imageStorageRef.putData(imageData, metadata: nil) { (metadata, error) in
                            guard let metadata = metadata else {
                                // Uh-oh, an error occurred!
                                return
                            }
                            // Metadata contains file metadata such as size, content-type
                            let size = metadata.size

                            // You can also access to download URL after upload.
                            imageStorageRef.downloadURL(completion: { (url, error) in
                                guard let downloadURL = url else {
                                    // Uh-oh, an error occurred!
                                    return
                                }
                                self!.imageDownloadURL = downloadURL.absoluteString
                                imageRef.child("imageDownloadURL").setValue(self!.imageDownloadURL)
                            })
                        }
                    }
                }
            }
        }
    }
    saveGeoFire()
}

1 个答案:

答案 0 :(得分:0)

您可以在数据库中创建子级的数据库引用变量,因此您不必一直输入.child

我建议尝试像这样使用Swift Dictionary一次保存所有值:

// in your loop where you start writing to Firebase   
if let databaseRef = databaseRef?.child("Event").child(fireKey) {
    let objectToSave = [
        "eventCategory": event.eventCatagory,
        "eventCity": event.eventCity,
        "eventContact": event.eventContact,
        // and so on...
        "eventStreet": event.eventStreet

    ] as [String:Any]
    databaseRef.setValue(objectToSave) { error, ref in
         if error != nil {
              // error handle
         } else {
              // then upload your photo since the write was successful
         } 
    }
}

第二,由于您正在循环中运行异步代码(写入Firebase),因此您将需要适当地处理此问题,因为代码将在数据库调用之前执行。

我建议您考虑使用DispatchQueue。以下是一些StackOverflow相关文章,可以教您如何将其实现到异步函数中:

Wait until swift for loop with asynchronous network requests finishes executing