繁体   English   中英

如何从 Swift 中的 Firestore 读取多个自定义对象

[英]How to read multiple custom objects from Firestore in Swift

使用 文档中的示例(对于 Swift)。 这是阅读多个文档的推荐方式:

db.collection("cities").whereField("capital", isEqualTo: true)
    .getDocuments() { (querySnapshot, err) in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            for document in querySnapshot!.documents {
                print("\(document.documentID) => \(document.data())")
            }
        }
}

这里推荐阅读自定义 object 的方法:

let docRef = db.collection("cities").document("BJ")

docRef.getDocument { (document, error) in
    let result = Result {
        try document.flatMap {
            try $0.data(as: City.self)
        }
    }
    switch result {
    case .success(let city):
        if let city = city {
            print("City: \(city)")
        } else {
            print("Document does not exist")
        }
    case .failure(let error):
        print("Error decoding city: \(error)")
    }
}

没有读取多个自定义对象的示例。 这是我基于前两个示例的尝试:

db.collection("cities").whereField("capital", isEqualTo: true)
    .getDocuments() { (querySnapshot, err) in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
            if let snapshotDocuments = querySnapshot?.documents {
                for document in snapshotDocuments {        
                    let result = Result {
                        try document.flatMap { // error: Value of type 'QueryDocumentSnapshot' has no member 'flatMap'
                            try $0.data(as: City.self)
                        }
                    }
                    switch result {
                    case .success(let city):
                        if let city = city {
                            print("City: \(city)")
                        } else {
                            print("Document does not exist")
                        }
                    case .failure(let error):
                        print("Error decoding city: \(error)")
                    }
                }
            }
        }
    }
}

基于错误(我已将其内容放在上面代码中的注释中),我假设在查询单个 object 或多个时文档对象的类是不同的,即使它们通常的用途是相同的。 我应该如何更改加载多个自定义对象的代码以使其正常工作?

在第一个示例中,getDocument 返回一个 DocumentSnapshot,它是 DocumentSnapshot 的子集? 这是可选的,因此它可以与结果 object.flatmap 一起使用。

在第二个示例中,getDocuments 不返回 DocumentSnapshot,而是返回一个 QueryDocumentSnapshot:

QueryDocumentSnapshots 保证它们的内容总是非空的

所以这意味着它不是可选的,不能与 .flatmap 一起使用,因为它不能被解包。

Firebase 文档显示QueryDocumentSnapshot是 DocumentSnapshot 的子类,DocumentSnapshot 是可选的,QueryDocumentSnapshot 不是。

在这种情况下,.flatmap 被用来解开 DocumentSnapshot(一个可选的) - 发生的事情是 Result 中的 object 如果没有它,将是双重包装的可选。 So.flatmap 解开它一次,然后if let city = city {再次解开它,所以它最终只是城市 object。

这就是我要做的......用这样的东西替换那个代码

func getCities() {
    let docRef = db.collection("cities")
    docRef.getDocuments { (querySnapshot, error) in
        if let snapshotDocuments = querySnapshot?.documents {
            for document in snapshotDocuments {
                do {
                    if let city = try document.data(as: City.self) {
                        print(city.name)
                    }
                } catch let error as NSError {
                    print("error: \(error.localizedDescription)")
                }
            }
        }
    }
}

编辑

我将从 github 借用这个,因为它使结果的使用(如文档中所示)更加清晰。

There are thus three cases to handle, which Swift lets us describe
nicely with built-in sum types:

      Result
        /\
   Error  Optional<City>
               /\
            Nil  City //<- we get the actual city with `if let city = city {`

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM