SWIFT IOS: не все данные сохраняются в firebase - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть следующий код, и я пытаюсь сохранить данные в базе данных.Экономия очень случайная.Иногда только первая .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 голосов
/ 29 ноября 2018

Вы можете создать ссылочную переменную базы данных дочерних элементов в вашей базе данных, поэтому вам не придется постоянно вводить .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, которые могут научить вас, как внедрить это в ваши асинхронные функции:

Дождитесь окончания выполнения цикла swift for с асинхронными сетевыми запросами

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...