将数据从 Firestore 映射到 Swift 中的结构 - IOS
Posted
技术标签:
【中文标题】将数据从 Firestore 映射到 Swift 中的结构 - IOS【英文标题】:Map Data From Firestore to a struct In Swift - IOS 【发布时间】:2019-06-07 09:43:29 【问题描述】:我正在尝试将从我的 Firestore 数据库中检索到的“用户”映射到我在代码中定义的用户结构,但我认为我没有正确理解 swift 中的映射功能。
如何将检索到的用户映射到结构中?
结构
struct User
// Properties
var firstName: String
var lastName: String
var userName: String
var email: String
init(firstName: String, lastName: String, userName: String, email: String)
self.firstName = firstName
self.lastName = lastName
self.userName = userName
self.email = email
从 Firestore 获取用户的函数
func getUser(UID: String)
// Firebase setup
settings.areTimestampsInSnapshotsEnabled = true
db.settings = settings
db.collection("users").document(UID).getDocument (document, error) in
if let error = error
print("Error: \(error.localizedDescription)")
else
print(document!.data()!)
【问题讨论】:
不相关,但您在User
结构中提供的 init
是不必要的。您将自动获得相同的init
,而无需自己编写。
哦,谢谢你的提示!我没有意识到它是自动的。您是否碰巧知道如何通过@rmaddy 进行这种映射?
***.com/questions/43786471/… 这个呢?
该解决方案绝对有效!但是有没有办法使用 swift 中的映射功能来做到这一点?我计划构建的一些数据库模型会更大更复杂。我也只是想学习如何使用这些功能以供将来参考@emrepun
你可能想让你的结构符合Codable
协议(Encodable & Decodable
)。如果您的结构只是字符串,则您无需实现任何东西,只需符合该协议即可完成,否则,如果您的 User
结构中有子对象,您将不得不编写自己的解析。有了这个,您可以使用快照中的字典来构建User
。
【参考方案1】:
查询的 Firestore 文档的类型为 [String: Any]
,因此请配置您的初始化程序以接受该类型的字典。因为您正在处理数据库返回,所以永远不能保证数据会完全完整,所以我建议让您的初始化程序失败,这意味着它可以返回 nil
(它可能会失败)。
我以您的为例,将email
属性设为可选。在下面的示例中,实例化User
对象只需要四个属性中的三个。
let info: [String: Any] = ["hasFriends": true]
let firestoreData: [String: Any] = ["firstName": "lance", "lastName": "stevenson", "userName": "lstevenson", "info": info]
struct User
var firstName: String
var lastName: String
var userName: String
var info: [String: Any]
var email: String?
var hasFriends: Bool
init?(data: [String: Any])
guard let firstName = data["firstName"] as? String,
let lastName = data["lastName"] as? String,
let userName = data["userName"] as? String,
let info = data["info"] as? [String: Any],
let hasFriends = info["hasFriends"] as? Bool else
return nil
self.firstName = firstName
self.lastName = lastName
self.userName = userName
self.info = info
self.hasFriends = hasFriends
self.email = data["email"] as? String // User will be created even if this is nil
if let user = User(data: firestoreData)
print(user.hasFriends) // true
我不建议您为此使用 Swift 的映射工具,因为您可能会在同一个字典中为不同的模型处理不同类型的值。并且在初始化程序中用这些变量映射这个字典的代码并不漂亮。
【讨论】:
这个解决方案效果很好,我从来没有想过!但是,假设在我的 firebase 数据库中,我有一个“信息”属性,它本身就是一个不同类型的字典。例如,它有一个字典,其中包含用户的好友列表,以及布尔值等不同的属性。如何在 swift 中访问从这个嵌套属性返回的特定属性? 我更新了我的答案。将其复制并粘贴到 Playground 中,然后随意玩弄,直到您感到舒服为止。 这非常有效!正如您可能知道的那样,我是编码新手,因此将每个属性设为可选是标准做法吗,因为理论上数据库调用可能会像您所说的那样返回部分数据? 这是需要考虑的一件事。要考虑的另一件事是,如果您将它们全部设为可选并且它们全部/大部分为零,您真的会使用该用户对象吗?您的 UI 是否会更好地丢弃该用户并获得下一个用户?我们也在与谷歌打交道;可靠性并没有变得更高。但最终决定权在你,作为工程师。什么对你最有意义?就个人而言,我会假设 Firebase 和网络将在 99.x% 的时间内交付,因此我不会将它们全部设为可选,但我会保持初始化程序作为一般安全网失效。 我觉得使用 nil 合并运算符会更合适,而不是在缺少某些值时使整个用户失败。例如:self.firstName = firstName ?? "ERR"
以上是关于将数据从 Firestore 映射到 Swift 中的结构 - IOS的主要内容,如果未能解决你的问题,请参考以下文章
如何将 ViewModel 的 ID 映射到 Firestore 中的文档 ID?
如何将一组地图从 Firestore 映射到 recyclerView?
使用 Stream 从 FireStore 获取数据并将其映射到 Flutter 类