Почему преобразование querySnapshot Firestore в пользовательские объекты с помощью compactMap возвращает пустое значение, хотя querySnapshot содержит документы? - PullRequest
0 голосов
/ 14 марта 2020

Скриншот документа Firestore

Я использую Swift, Xcode и базу данных Firestore. Я создал TableView и пользовательский класс объектов (MediumSample) со словарем и хочу загрузить свои документы Firestore и показать их в TableView.

Документы (пример на скриншоте) загружаются из Firestore корректно, но преобразование в объект не сработало. Список объектов, возвращаемых из compactMap, всегда пуст.

Вот мои фрагменты кода. Было бы здорово, если бы у кого-то был намек на то, что идет не так.

Класс пользовательских объектов (упрощенный):

import Foundation
import FirebaseFirestore

protocol MediumSampleDocumentSerializable {
    init?(dictionary: [String:Any])
}

struct MediumSample {

    var id: String
    var field_t: String
    var field_i: Int64
    var field_b1: Bool
    var field_b2: Bool
    var field_g: FirebaseFirestore.GeoPoint
    var field_d: Date
    var field_a: [String]
    var usecase: String


    var dictionary: [String:Any] {
         return [
             "id": id,
             "field_t": field_t,
             "field_i": field_i,
             "field_b1": field_b1,
             "field_b2": field_b2,
             "field_g": field_g,
             "field_d": field_d,
             "field_a": field_a,
             "usecase": usecase
         ]
     }

}

extension MediumSample: MediumSampleDocumentSerializable {
    init?(dictionary: [String:Any]) {
        guard let id = dictionary ["id"] as? String,
        let field_t = dictionary ["field_t"] as? String,
        let field_i = dictionary ["field_i"] as? Int64,
        let field_b1 = dictionary ["field_b1"] as? Bool,
        let field_b2 = dictionary ["field_b2"] as? Bool,
        let field_g = dictionary ["field_g"] as? FirebaseFirestore.GeoPoint,
        let field_d = dictionary ["field_d"] as? Date,
        let field_a = dictionary ["field_a"] as? [String],
        let usecase = dictionary ["usecase"] as? String else {return nil}

        self.init (id: id, field_t: field_t, field_i: field_i, field_b1: field_b1, field_b2: field_b2, field_g: field_g, field_d: field_d, field_a: field_a, usecase: usecase)
    }

}

Объявление базы данных и массива и вызов функции загрузки:

import UIKit
import FirebaseFirestore

class MediumTableViewController: UITableViewController {

    //MARK: Properties

    var db: Firestore!
    var mediumsamples = [MediumSample]()

    override func viewDidLoad() {
        super.viewDidLoad()

        db = Firestore.firestore()
        loadMediumSamples()

    }

Функция загрузки документов Firestore в заполните массив:

    private func loadMediumSamples() {

               //run the Firestore query
               db.collection(Constants.MEDIUMS).whereField("usecase", isEqualTo: Constants.USECASE)
                   .getDocuments() { querySnapshot, err in
                       if let err = err {
                           print("Error getting documents: \(err)")
                       } else {

                        //initialise an array of medium objects with Firestore data snapshots
                        self.mediumsamples = querySnapshot!.documents.compactMap({MediumSample(dictionary: $0.data())})

                        //fill the tableView
                        DispatchQueue.main.async {
                            self.tableView.reloadData()
                            print(self.mediumsamples)
                        }

                        print("Mediums List", self.mediumsamples) // This line returns: Mediums List []

                        print("Mediums List size", (self.mediumsamples.count)) // This line returns: Mediums List size 0

                        for document in querySnapshot!.documents {
                            print("\(document.documentID) => \(document.data())") // This line returns the snapshot documents correctly!

                        }
                       }
               }
    }

Вот как добавляется объект снимка экрана:

    func addMediumSamples() {

        let currentDateTime = Date()
        let location = FirebaseFirestore.GeoPoint(latitude: 0, longitude: 0)
        let mediumsample = MediumSample(id: "an id", field_t: "field_t", field_i: 10, field_b1: true, field_b2: false, field_g: location, field_d: currentDateTime, field_a: [Constants.SAMPLE_DEV], usecase: Constants.SAMPLE_DEV)

        var ref: DocumentReference? = nil
        ref = self.db.collection(Constants.MEDIUMS).addDocument(data: mediumsample.dictionary) {
            error in
            if let error = error {
                print("Error writing city to Firestore: \(error)")
            } else {
                print("Document added with id : \(ref!.documentID)")
            }
        }

    }

1 Ответ

0 голосов
/ 14 марта 2020

Проблема в структуре MediumSample , в типе field_d (Дата). Тип этого поля в базе данных Cloud Firestore: отметка времени .

Поле "field_d" в структуре MediumSample ожидает значение типа Date .

Вы можете изменить тип на FirebaseFirestore.Timestamp или преобразовать его в Дата при отображении и перед передачей в MediumSample.

например. для преобразования метки времени в дату в Swift

let date = timestamp.dateValue ()

...