尽管querySnapshot包含文档,为什么将Firestore querySnapshot转换为带有compactMap的自定义对象,却返回空? [英] Why converting a Firestore querySnapshot into custom objects with compactMap returns empty although the querySnapshot contains documents?

查看:61
本文介绍了尽管querySnapshot包含文档,为什么将Firestore querySnapshot转换为带有compactMap的自定义对象,却返回空?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Firestore文档的屏幕截图

我正在使用Swift,Xcode和Firestore数据库.我创建了TableView和带有字典的自定义对象类(MediumSample),并希望加载Firestore文档并在TableView中显示它们.

已正确从Firestore加载了文档(屏幕截图中的示例),但无法转换为对象.从compactMap返回的对象列表始终为空.

这是我的代码段.如果有人对出了什么问题有暗示,那就太好了.

自定义对象类(简化):

  import Foundation导入FirebaseFirestore协议MediumSampleDocumentSerializable {初始化?(字典:[String:Any])}struct MediumSample {var id:字符串var field_t:字符串var field_i:Int64var field_b1:布尔var field_b2:布尔var field_g:FirebaseFirestore.GeoPointvar field_d:日期var field_a:[字符串]var用例:字符串var字典:[String:Any] {返回 ["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,用例":用例]}}扩展程序MediumSample:MediumSampleDocumentSerializable {初始化?(字典:[String:Any]){警卫让id =字典["id"]为?细绳,让field_t =字典["field_t"]为?细绳,让field_i =字典["field_i"]为?Int64,让field_b1 =字典["field_b1"]为?布尔,让field_b2 =字典["field_b2"]为?布尔,让field_g =字典["field_g"]为?FirebaseFirestore.GeoPoint,让field_d =字典["field_d"]为?日期,让field_a =字典["field_a"]为?[细绳],让用例=字典[用例"]为?其他字符串{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,用例:用例)}} 

声明数据库和数组并调用加载函数:

 导入UIKit导入FirebaseFirestore类MediumTableViewController:UITableViewController {//MARK:属性var db:Firestore!var mediumsamples = [MediumSample]()覆盖func viewDidLoad(){super.viewDidLoad()db = Firestore.firestore()loadMediumSamples()} 

用于加载Firestore文档以填充数组的功能:

 私有函数loadMediumSamples(){//运行Firestore查询db.collection(Constants.MEDIUMS).whereField("usecase",isEqualTo:Constants.USECASE).getDocuments(){querySnapshot,err in如果让err = err {print(获取文档时出错:\(err)")} 别的 {//使用Firestore数据快照初始化一系列中型对象self.mediumsamples = querySnapshot!.documents.compactMap({MediumSample(dictionary:$ 0.data())})//填写tableViewDispatchQueue.main.async {self.tableView.reloadData()打印(self.mediumsamples)}print("Mediums List",self.mediumsamples)//此行返回:Mediums List []print("Mediums List size",(self.mediumsamples.count))//此行返回:Mediums List size 0用于querySnapshot!.documents中的文档{print("\(document.documentID)=> \(document.data())")//此行正确返回快照文档!}}}} 

以下是添加屏幕快照对象对象的方式:

  func addMediumSamples(){让currentDateTime = Date()let location = FirebaseFirestore.GeoPoint(纬度:0,经度:0)让mediumsample = MediumSample(id:一个id",field_t:"field_t",field_i:10,field_b1:true,field_b2:false,field_g:位置,field_d:currentDateTime,field_a:[Constants.SAMPLE_DEV],用例:常量.SAMPLE_DEV)var ref:DocumentReference?=无ref = self.db.collection(Constants.MEDIUMS).addDocument(data:mediumsample.dictionary){错误中如果让错误=错误{print(将城市写入Firestore时出错:\(错误)")} 别的 {print(添加了ID的文档:\(ref!.documentID)")}}} 

解决方案

问题出在 MediumSample结构中,类型为 field_d (日期).Cloud Firestore数据库中该字段的类型为时间戳.

MediumSample结构中的字段"field_d" 期望值为 Date 类型.

您可以将类型更改为 FirebaseFirestore.Timestamp ,也可以在映射时以及传递给MediumSample之前将其转换为 Date .

例如在Swift中将时间戳转换为日期

让日期= timestamp.dateValue()

Screenshot of a Firestore Document

I am using Swift, Xcode and a Firestore database. I created a TableView and a Custom Object Class (MediumSample) with a dictionary and want to load my Firestore documents and show them in the TableView.

The documents (example in the screenshot) are loaded from Firestore correctly but the conversion into the object did not work. The list of objects returned from compactMap is always empty.

Here is my code snippets. It would be great, if someone has a hint on what is going wrong.

Custom Object Class (simplified):

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)
    }

}

Declaration of the database and array and calling the loading function:

import UIKit
import FirebaseFirestore

class MediumTableViewController: UITableViewController {

    //MARK: Properties

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

    override func viewDidLoad() {
        super.viewDidLoad()

        db = Firestore.firestore()
        loadMediumSamples()

    }

Function for loading the Firestore documents to fill the Array:

    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!

                        }
                       }
               }
    }

Here is how the screenshot object object is added:

    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)")
            }
        }

    }

解决方案

The problem is in the MediumSample struct, in the field_d type (Date). The type of that field in your Cloud Firestore database is Timestamp.

The field "field_d" in the MediumSample struct expects a value of type Date.

You can change the type to the FirebaseFirestore.Timestamp, or you can convert it to Date when mapping and before passing to the MediumSample.

eg. for converting Timestamp to Date in Swift

let date = timestamp.dateValue()

这篇关于尽管querySnapshot包含文档,为什么将Firestore querySnapshot转换为带有compactMap的自定义对象,却返回空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆