0

我正在尝试在 Swift 中实现 NSXMLParserDelegate,但在某些委托方法中使用属性字典时遇到问题。例如,在parser:didStartElement:

func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!) {

尝试访问 attributeDict 值,例如:

if self.feedType == FeedType.RSS {
    self.insideLink = true
} else {
    if (String(attributeDict["rel"]) == "alternate") && (String(attributeDict["type"]) == "text/html") {
        self.link = String(attributeDict["href"])
        self.insideLink = false
        self.doneWithLink = true
    }
}

我收到一条错误消息:“'String' 不能转换为 'FeedType'”。

enum FeedType:String {

    case ATOM = "feed"
    case RSS = "rss"

}

class FeedParser:NSObject, NSXMLParserDelegate {

    var feedType:FeedType?

是一个错误。主题的其他十几个变体也是如此……有什么见解吗?

我想问题是如何正确使用attributeDicttype的键/值对[NSObject: AnyObject]

4

1 回答 1

4

看起来你可能有一个虚假的错误信息:我建议提交一个错误

我想问题是如何正确使用attributeDict类型的键/值对[NSObject: AnyObject]

你是对的:这看起来是问题的根源。解决方案不是从字典查找中构造a ,而是(有条件地)强制转换为. 也就是说,与其尝试从不确定(和可选)类型的引用创建一个新的,不如询问 Swift 该引用是否实际上是对可以解释为的东西:StringStringStringString

let rel = attributeDict["rel"] as? String

这为您提供了一个可选的,因为attributeDict可能不包含 key 的值rel,并且因为条件转换可能会失败(attributeDict["rel"]可能是不同类型的值)。因为您需要检查两个条件强制转换及其展开的值,所以您最终可能会得到很多强制展开运算符 ( !) 或深度嵌套if-let的块......这会很快变得丑陋。

Optional相反,您可以利用枚举这一事实。它的定义看起来像这样:

enum Optional<T> {
    case None    // aka nil
    case Some(T) // what you get when you unwrap a non-nil optional
}

有了它,您可以使用模式匹配来安全简洁地进行查找、转换、解包和测试:

switch (attributeDict["rel"] as? String, attributeDict["type"] as? String) {
  case let (.Some(rel), .Some(type)) where rel == "alternate" && type == "text/html":
    // harvest link
  default:
    // no match... fall back to other behavior, log an error, etc
}

请注意,在“收获链接”步骤中,您仍然需要有条件地强制转换和展开attributeDict["href"]查找。您可以通过if-let在 that 中嵌套一个构造case或向元组添加第三个查找来做到这一点switch


顺便说一句,self.在 Swift 中所有的符号都是不必要的(除非你在一个闭包中或者需要从实例属性中消除方法参数的歧义)。

于 2014-07-29T22:24:39.393 回答