Skip to main content
 首页 » 操作系统

ios之Swift 循环遍历具有多维数组的 Dictionary plist

2024年01月01日56xxx_UU

我有一个 plist,其设置如下所示:

我想将它加载到一个变量中,然后遍历每个项目。这是我目前的代码,但无济于事,我看到错误“Type 'AnyObject' does not conform to protocol '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 
    } 
} 

请您参考如下方法:

您遇到的问题是基础类处理 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 子句。