简体   繁体   English

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

[英]Swift loop over a Dictionary plist with multidimensional array

I have a plist that is set up as shown below: 我有一个设置如下所示的plist:

在此输入图像描述

I'd like to load this into a variable and then loop over each of the items. 我想将其加载到变量中,然后循环遍历每个项目。 This is the code I have so far, but to no avail I am seeing the error "Type 'AnyObject' does not conform to protocol 'SequenceType'". 这是我到目前为止的代码,但无济于事我看到错误“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
    }
}

The problem you are having is that the foundation classes deal in AnyObject s, but for thinks like for loops that doesn't work: 您遇到的问题是基础类在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 ! :)

You may find it easier to convert earlier to Swift types and then use them directly. 您可能会发现更容易先前转换为Swift类型,然后直接使用它们。 The downside of this is if you are storing heterogenous data in your plist (ie an array that has both strings and integers in it). 这样做的缺点是,如果要在plist中存储异构数据(即包含字符串和整数的数组)。 But it doesn't look you do, so you could write your code like this: 但它看起来不像你这样做,所以你可以像这样编写你的代码:

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

        }
    }
}

Personally, I find this much easier to understand at a glance because the types you are dealing with at each level are easier to see and understand and you're not mashing away with as? 就个人而言,我发现这一目击起来更容易理解,因为你在每个级别处理的类型更容易看到和理解,你不会捣乱as? and is etc. The big downside to this is if you want to handle multiple different types within the same collection. 并且is等大的缺点是,如果你想在同一集合内处理多种不同的类型。 Then you need to leave things as AnyObject a bit longer, and do more fine-grained as? 然后你需要将AnyObject的内容保留更长时间,并做得更精细as? in the inner loops. 在内循环中。

Once you have the above, there are various tricks you can do to handle the optionals better and avoid so many horrid if let s, replace loops with maps and filters etc., but it's probably better to get comfortable with this version first. 一旦你有了上述内容,你可以做各种各样的技巧来更好地处理选项, if let s,用地图和过滤器替换循环等,可以避免这么多可怕的事情,但最好先熟悉这个版本。 Also, this code is missing various else clauses that could handle and report failure cases. 此外,此代码缺少可以处理和报告故障情况的else各种子句。

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

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