Swift循环遍历具有多维数组的字典plist

时间:2015-01-12 14:45:03

标签: ios swift

我有一个如下图所示设置的plist:

enter image description here

我想将其加载到变量中,然后循环遍历每个项目。这是我到目前为止的代码,但无济于事我看到了错误" Type' AnyObject'不符合协议' SequenceType'"。

func startTournament(sender: UIBarButtonItem) {
    var map: NSDictionary?
    if let path = NSBundle.mainBundle().pathForResource("knockout_single_8", ofType: "plist") {
        map = NSDictionary(contentsOfFile: path)
    }

    var matches = NSMutableDictionary()
    let rounds = map?["rounds"] as NSArray
    for match in rounds[0] { // Error from this line
        let mid = match["mid"]
        let match = ["names": ["testA", "testB"]]
        matches[mid] = match
    }
}

1 个答案:

答案 0 :(得分:3)

您遇到的问题是基础类在AnyObject中处理,但对于像for循环这样的思想不起作用:

import Foundation
let o: AnyObject = [1,2,3]

// this won't work, even though o _is_ an array
// error: type 'AnyObject' does not conform to protocol 'SequenceType'
for i in o {

}

// this is perhaps surprising given this does:
o[0]  // returns 1 as an AnyObject! (that's a syntactic ! not a surprise/shock ! :)

您可能会发现更容易将之前的转换为Swift类型,然后直接使用它们。这样做的缺点是,如果要在plist中存储异构数据(即包含字符串和整数的数组)。但它看起来并不像你这样做,所以你可以像这样编写你的代码:

func startTournament() {
    if let path = NSBundle.mainBundle().pathForResource("proplist", ofType: "plist") {
        if let map = NSDictionary(contentsOfFile: path) {

            var matches: [Int:[String:[String]]] = [:]

            if let rounds = map["rounds"] as? [[[String:Int]]] {

                for match in rounds[0] {
                    if let mid = match["mid"] {
                        let match = ["names": ["testA", "testB"]]
                        matches[mid] = match
                    }
                }
            }

        }
    }
}

就我个人而言,我发现这一目标更容易理解,因为您在每个级别处理的类型更容易查看和理解,而且您不会使用as?is进行捣乱如果你想在同一个系列中处理多种不同的类型,那么最大的缺点是。然后你需要将AnyObject更长一些,并在内循环中做更精细的as?

一旦你有了上述内容,你可以采取各种措施来更好地处理选项,并避免这么多可怕的if let,用地图和过滤器替换循环等等,但最好还是舒服一点。这个版本第一。此外,此代码缺少可处理和报告失败案例的各种else子句。