如何使用 SWXMLHash 反序列化 NSDate
How to deserialize NSDate with SWXMLHash
我正在使用 SWXMLHash 并在 NSDate
上为 XMLElementDeserializable.
写了一个 extension
我在 this file 的末尾了解了基本类型是如何扩展的。
我得到的是这样的:
import Foundation
import SWXMLHash
struct BlogPost: XMLIndexerDeserializable {
let date: NSDate
static func deserialize(blogPost: XMLIndexer) throws -> BlogPost {
return try BlogPost(
date: blogPost["date"].value()
)
}
}
extension NSDate: XMLElementDeserializable {
/**
Attempts to deserialize XML element content to an NSDate
- element: the XMLElement to be deserialized
- throws: an XMLDeserializationError.TypeConversionFailed if the element cannot be deserialized
- returns: the deserialized NSDate value formatted as "EEE, dd MMM yyyy HH:mm:ss zzz"
*/
public static func deserialize(element: XMLElement) throws -> NSDate {
guard let dateAsString = element.text else {
throw XMLDeserializationError.NodeHasNoValue
}
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz"
let date = dateFormatter.dateFromString(dateAsString)
guard let validDate = date else {
throw XMLDeserializationError.TypeConversionFailed(type: "Date", element: element)
}
return validDate
}
}
但是,我收到一条错误消息:
Method 'deserialize' in non-final class 'NSDate' must return 'Self' to
conform to protocol 'XMLElementDeserializable'
我环顾四周 S.O。对于同一错误的其他答案,我没有从他们那里收集到太多信息。
如有任何建议,我们将不胜感激。谢谢!
好吧,这很奇怪,但问题是存在的,因为 NSDate
是 class
而不是 struct
。显然需要一些工作才能使 class 符合 returns 自身的协议 - 让它与结构一起工作要容易得多!
(在 Swift 4 中,这是不必要的,因为 Date
是一个结构)
我将不得不添加一些额外的文档来展示它是如何工作的。
检查以下代码(根据您的示例修改)以查看它是否适合您:
import Foundation
import SWXMLHash
extension NSDate: XMLElementDeserializable {
// NOTE: for SWXMLHash 3.0 with Swift 3.0, this will be (_ element: XMLElement)
public static func deserialize(element: XMLElement) throws -> Self {
guard let dateAsString = element.text else {
throw XMLDeserializationError.NodeHasNoValue
}
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz"
let date = dateFormatter.dateFromString(dateAsString)
guard let validDate = date else {
throw XMLDeserializationError.TypeConversionFailed(type: "Date", element: element)
}
// NOTE THIS
return value(validDate)
}
// AND THIS
private static func value<T>(date: NSDate) -> T {
return date as! T
}
}
let xml = "<root><elem>Monday, 23 January 2016 12:01:12 111</elem></root>"
let parser = SWXMLHash.parse(xml)
let dt: NSDate = try! parser["root"]["elem"].value()
另见 and 。
注意:添加了注释,指出这对于 SWXMLHash 3.0 看起来会略有不同。
如果有人需要,这里是 Swift 4 的实现:
extension Date: XMLElementDeserializable, XMLAttributeDeserializable {
public static func deserialize(_ element: SWXMLHash.XMLElement) throws -> Date {
guard !element.text.isEmpty else {
throw XMLDeserializationError.nodeHasNoValue
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = FeedParser.dateFormat
guard let date = dateFormatter.date(from: element.text) else {
throw XMLDeserializationError.typeConversionFailed(type: "Date", element: element)
}
return date
}
public static func deserialize(_ attribute: XMLAttribute) throws -> Date {
guard !attribute.text.isEmpty else {
throw XMLDeserializationError.nodeHasNoValue
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = FeedParser.dateFormat
guard let date = dateFormatter.date(from: attribute.text) else {
throw XMLDeserializationError.attributeDeserializationFailed(type: "Date", attribute: attribute)
}
return date
}
}
我正在使用 SWXMLHash 并在 NSDate
上为 XMLElementDeserializable.
extension
我在 this file 的末尾了解了基本类型是如何扩展的。
我得到的是这样的:
import Foundation
import SWXMLHash
struct BlogPost: XMLIndexerDeserializable {
let date: NSDate
static func deserialize(blogPost: XMLIndexer) throws -> BlogPost {
return try BlogPost(
date: blogPost["date"].value()
)
}
}
extension NSDate: XMLElementDeserializable {
/**
Attempts to deserialize XML element content to an NSDate
- element: the XMLElement to be deserialized
- throws: an XMLDeserializationError.TypeConversionFailed if the element cannot be deserialized
- returns: the deserialized NSDate value formatted as "EEE, dd MMM yyyy HH:mm:ss zzz"
*/
public static func deserialize(element: XMLElement) throws -> NSDate {
guard let dateAsString = element.text else {
throw XMLDeserializationError.NodeHasNoValue
}
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz"
let date = dateFormatter.dateFromString(dateAsString)
guard let validDate = date else {
throw XMLDeserializationError.TypeConversionFailed(type: "Date", element: element)
}
return validDate
}
}
但是,我收到一条错误消息:
Method 'deserialize' in non-final class 'NSDate' must return 'Self' to conform to protocol 'XMLElementDeserializable'
我环顾四周 S.O。对于同一错误的其他答案,我没有从他们那里收集到太多信息。
如有任何建议,我们将不胜感激。谢谢!
好吧,这很奇怪,但问题是存在的,因为 NSDate
是 class
而不是 struct
。显然需要一些工作才能使 class 符合 returns 自身的协议 - 让它与结构一起工作要容易得多!
(在 Swift 4 中,这是不必要的,因为 Date
是一个结构)
我将不得不添加一些额外的文档来展示它是如何工作的。
检查以下代码(根据您的示例修改)以查看它是否适合您:
import Foundation
import SWXMLHash
extension NSDate: XMLElementDeserializable {
// NOTE: for SWXMLHash 3.0 with Swift 3.0, this will be (_ element: XMLElement)
public static func deserialize(element: XMLElement) throws -> Self {
guard let dateAsString = element.text else {
throw XMLDeserializationError.NodeHasNoValue
}
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz"
let date = dateFormatter.dateFromString(dateAsString)
guard let validDate = date else {
throw XMLDeserializationError.TypeConversionFailed(type: "Date", element: element)
}
// NOTE THIS
return value(validDate)
}
// AND THIS
private static func value<T>(date: NSDate) -> T {
return date as! T
}
}
let xml = "<root><elem>Monday, 23 January 2016 12:01:12 111</elem></root>"
let parser = SWXMLHash.parse(xml)
let dt: NSDate = try! parser["root"]["elem"].value()
另见
注意:添加了注释,指出这对于 SWXMLHash 3.0 看起来会略有不同。
如果有人需要,这里是 Swift 4 的实现:
extension Date: XMLElementDeserializable, XMLAttributeDeserializable {
public static func deserialize(_ element: SWXMLHash.XMLElement) throws -> Date {
guard !element.text.isEmpty else {
throw XMLDeserializationError.nodeHasNoValue
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = FeedParser.dateFormat
guard let date = dateFormatter.date(from: element.text) else {
throw XMLDeserializationError.typeConversionFailed(type: "Date", element: element)
}
return date
}
public static func deserialize(_ attribute: XMLAttribute) throws -> Date {
guard !attribute.text.isEmpty else {
throw XMLDeserializationError.nodeHasNoValue
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = FeedParser.dateFormat
guard let date = dateFormatter.date(from: attribute.text) else {
throw XMLDeserializationError.attributeDeserializationFailed(type: "Date", attribute: attribute)
}
return date
}
}