我正在尝试扩展功能Date.init(from:Decoder)
以处理从我的服务器传递的不同格式。有时日期将被编码为字符串,有时该字符串嵌套在字典中。根据 Swift 来源,Date
解码/编码如下:
extension Date : Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let timestamp = try container.decode(Double.self)
self.init(timeIntervalSinceReferenceDate: timestamp)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.timeIntervalSinceReferenceDate)
}
}
因此,我尝试按如下方式扩展该功能:
public extension Date {
private enum CodingKeys: String, CodingKey {
case datetime
}
public init(from decoder: Decoder) throws {
let dateString: String
if let container = try? decoder.container(keyedBy: CodingKeys.self) {
dateString = try container.decode(String.self, forKey: .datetime)
} else if let string = try? decoder.singleValueContainer().decode(String.self) {
dateString = string
} else {
let timestamp = try decoder.singleValueContainer().decode(Double.self)
self.init(timeIntervalSinceReferenceDate: timestamp)
return
}
if let date = Utils.date(from: dateString) {
self.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate)
} else if let date = Utils.date(from: dateString, with: "yyyy-MM-dd") {
self.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate)
} else {
let context = DecodingError.Context(codingPath: [], debugDescription: "Date format was unparseable.")
throw DecodingError.dataCorrupted(context)
}
}
}
然而,这个函数永远不会被调用。然后我尝试扩展KeyedDecodingContainer
以更改Date
解码decode(_:forKey)
如下:
extension KeyedDecodingContainer {
private enum TimeCodingKeys: String, CodingKey {
case datetime
}
func decode(_ type: Date.Type, forKey key: K) throws -> Date {
let dateString: String
if let timeContainer = try? self.nestedContainer(keyedBy: TimeCodingKeys.self, forKey: key) {
dateString = try timeContainer.decode(String.self, forKey: .datetime)
} else if let string = try? self.decode(String.self, forKey: key) {
dateString = string
} else {
let value = try self.decode(Double.self, forKey: key)
return Date(timeIntervalSinceReferenceDate: value)
}
if let date = Utils.date(from: dateString) {
return date
} else if let date = Utils.date(from: dateString, with: Globals.standardDateFormat) {
return date
} else {
let context = DecodingError.Context(codingPath: [], debugDescription: "Date format was not parseable.")
throw DecodingError.dataCorrupted(context)
}
}
}
但是,当调用它来解码Date
我通过调用编码的a 时container.encode(date, forKey: .date)
,我收到一个typeMismatch
错误,即数据不是 a Double
。我完全不知道发生了什么,因为encode(to:)
函数Date
显式地编码了一个 Double。我尝试通过 Swift 源代码中的调用来追踪我的方式decode
,但它似乎从来没有调用Date.init(from:Decoder)
.
所以我想知道,是否可以Date
通过这种扩展来改变类型的解码方式?我唯一的选择是Date
在每个模型中复制我的自定义解码吗?到底叫init(from:Decoder)
什么?