3

我正在使用SWXMLHashextensionNSDateXMLElementDeserializable.

我已经按照这个文件末尾的基本类型是如何扩展的。

我所拥有的看起来像这样:

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
    }
}

但是,我收到一条错误消息:

非最终类“NSDate”中的方法“反序列化”必须返回“Self”以符合协议“XMLElementDeserializable”

我环顾四周寻找相同错误的其他答案,但我没有从他们那里收集到太多信息。

任何建议将不胜感激。谢谢!

4

2 回答 2

2

好的,这很奇怪,但问题存在是因为NSDate是 aclass而不是 a struct。显然,要让一个类符合返回 self 的协议需要一些工作 - 让它与结构一起工作要容易得多!

(在 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()

另请参见Return instancetype in SwiftUsing 'self' in class extension functions in Swift

注意:添加了一条注释,指出这对于 SWXMLHash 3.0 看起来会略有不同。

于 2016-07-05T02:38:21.963 回答
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
    }
}
于 2017-10-08T13:28:03.403 回答