如何使用 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。对于同一错误的其他答案,我没有从他们那里收集到太多信息。

如有任何建议,我们将不胜感激。谢谢!

好吧,这很奇怪,但问题是存在的,因为 NSDateclass 而不是 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
    }
}