如果具有以下代码,则应将[String: any]
文档从Firestore转换为结构。
当时我进行调试时,所有条件都已满足,但返回后的值为nil
。
我尝试将init?
更改为常规init
,并将else { fatalError() }
上的guard
更改为 struct Banner {
let destinationUrl: URL
let imageUrl: URL
let endTime: Date
let startTime: Date
let priority: Int
let trackingKeyClicked: String
let trackingKeyDismissed: String
init?(document: [String: Any]) {
guard
let destinationUrlString = document["destinationUrl"] as? String,
let destinationUrl = URL(string: destinationUrlString),
let imageUrlString = document["imageUrl"] as? String,
let imageUrl = URL(string: imageUrlString),
let priority = document["priority"] as? Int,
let trackingKeyClicked = document["trackingKeyClicked"] as? String,
let trackingKeyDismissed = document["trackingKeyDismissed"] as? String,
let startTime = document["startTime"] as? Date,
let endTime = document["endTime"] as? Date
else { return nil }
self.destinationUrl = destinationUrl
self.imageUrl = imageUrl
self.priority = priority
self.trackingKeyClicked = trackingKeyClicked
self.trackingKeyDismissed = trackingKeyDismissed
self.endTime = endTime
self.startTime = startTime
}
}
// using it like this
let bannerStructs = querySnapshot.documents.map { Banner(document: $0.data()) }
。如果数据有效,它将起作用并返回有效的结构。
失败的初始化程序在做什么?
这不起作用(即使有有效数据也总是返回nil):
struct Banner {
let destinationUrl: URL
// ...
let endTime: Date
init(document: [String: Any]) {
guard
let destinationUrlString = document["destinationUrl"] as? String,
let destinationUrl = URL(string: destinationUrlString),
// ....
let endTime = document["endTime"] as? Date
else { fatalError() }
self.destinationUrl = destinationUrl
// ...
self.endTime = endTime
}
}
这适用于有效数据(但在错误数据上崩溃而不是返回nil):
useQuery
答案 0 :(得分:1)
如果没有一个guard let
条件得到满足,它将失败并最终触发fatalError或返回nil,这取决于您使用的实现方式。
请正确调试哪些数据没有正确解析/广播。
我设置了一个很好的示例来说明您可能希望它如何工作,而另一个不好的例子则是为了让您知道用这种格式无法预期的attribute
可以使{{ 1}}返回initialiser
:
nil
这是打印出来的内容:
import Foundation
struct Banner {
let destinationUrl: URL
let imageUrl: URL
let endTime: Date
let startTime: Date
let priority: Int
let trackingKeyClicked: String
let trackingKeyDismissed: String
init?(document: [String: Any]) {
guard
let destinationUrlString = document["destinationUrl"] as? String,
let destinationUrl = URL(string: destinationUrlString),
let imageUrlString = document["imageUrl"] as? String,
let imageUrl = URL(string: imageUrlString),
let priority = document["priority"] as? Int,
let trackingKeyClicked = document["trackingKeyClicked"] as? String,
let trackingKeyDismissed = document["trackingKeyDismissed"] as? String,
let startTime = document["startTime"] as? Date,
let endTime = document["endTime"] as? Date
else { return nil }
self.destinationUrl = destinationUrl
self.imageUrl = imageUrl
self.priority = priority
self.trackingKeyClicked = trackingKeyClicked
self.trackingKeyDismissed = trackingKeyDismissed
self.endTime = endTime
self.startTime = startTime
}
}
// using it like this
let goodData:[String:Any] = [
"destinationUrl": "http://destination--url",
"imageUrl": "http://image-url",
"priority": 17,
"trackingKeyClicked": "Tracking Key Clicked",
"trackingKeyDismissed": "Tracking Key Dismissed",
"startTime": Date(),
"endTime": Date()
]
let goodBannerStructs = Banner(document: goodData)
let badData:[String:Any] = [
"destinationUrl": "http://destination--url",
"imageUrl": "http://image-url",
"priority": 17,
"trackingKeyClicked": "Tracking Key Clicked",
"trackingKeyDismissed": "Tracking Key Dismissed",
"startTime": "17 December",
"endTime": Date()
]
let badBannerStructs = Banner(document: badData)
print("Good banner: \(goodBannerStructs)")
print("Bad banner: \(badBannerStructs)")
您可以在http://online.swiftplayground.run/
上尝试以下代码可能是Good banner: Optional(Banner(destinationUrl: http://destination--url, imageUrl: http://image-url, endTime: 2020-01-21 17:45:27 +0000, startTime: 2020-01-21 17:45:27 +0000, priority: 17, trackingKeyClicked: "Tracking Key Clicked", trackingKeyDismissed: "Tracking Key Dismissed"))
Bad banner: nil
的字典键可能与查询中的内容不正确,可能是document
可能不是Int或日期可能是String。您必须对其进行调试。
答案 1 :(得分:1)
如果可失败的初始化程序返回nil且正常的初始化程序由于数据损坏而崩溃,那么这将我引向可失败的初始化程序中的guard语句,导致该失败而返回nil。在guard语句内的return nil行上放置一个断点,看看是否被击中。
答案 2 :(得分:0)
这不起作用(即使有有效数据也总是返回nil)
由于您的guard
始终失败,因此数据似乎不正确。我猜想startDate
和endDate
转换为Date
并不是那么容易。您能发表一个json数据的例子吗?
如果这是原因,here就是描述如何使用DateFormatter
从字符串创建日期的人。如果您的日期遵循ISO8601,则可以使用苹果ISO8601DateFormatter
来完成。