简体   繁体   English

如何使用SWXMLHash反序列化NSDate

[英]How to deserialize NSDate with SWXMLHash

I'm using SWXMLHash and have written an extension on NSDate for XMLElementDeserializable. 我正在使用SWXMLHash并在NSDateXMLElementDeserializable.编写了一个extension XMLElementDeserializable.

I've followed how the basic types are extended at the end of this file . 我已经按照如何在此文件的末尾扩展基本类型。

What I have looks like this: 我看起来像这样:

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

However, I'm getting an error that says: 但是,我收到的错误是:

Method 'deserialize' in non-final class 'NSDate' must return 'Self' to conform to protocol 'XMLElementDeserializable' 非final类'NSDate'中的'deserialize'方法必须返回'Self'以符合协议'XMLElementDeserializable'

I've looked around SO for other answers to the same error and I haven't gleaned much information from them. 我已经环顾四周寻找同样错误的其他答案,我没有从他们那里收集到太多信息。

Any suggestions would be much appreciated. 任何建议将不胜感激。 Thanks! 谢谢!

Okay, this is pretty odd, but the problem exists because NSDate is a class instead of a struct . 好吧,这很奇怪,但问题存在是因为NSDate是一个class而不是struct It apparently takes some work to get a class to conform to a protocol that returns self - it is far easier to get this to work with a struct! 显然需要一些工作才能让一个类符合一个返回self的协议 - 这更容易让它与一个struct一起工作!

(in Swift 4, this is unnecessary as Date is a struct) (在Swift 4中,由于Date是结构,这是不必要的)

I'll have to add some additional documentation to show how this can work. 我将不得不添加一些额外的文档来说明这是如何工作的。

Check out the following code (modified from your example) to see if it works for you: 查看以下代码(从您的示例中修改)以查看它是否适合您:

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

See also Return instancetype in Swift and Using 'self' in class extension functions in Swift . 另请参见Swift中的返回instancetype和Swift 中类扩展函数中的“self”

NOTE : Added a comment noting that this will look slightly different for SWXMLHash 3.0. 注意 :添加了注释,注意到SWXMLHash 3.0看起来略有不同。

In case someone needs that, here is the implementation for Swift 4: 如果有人需要,这是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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM