遍历 .plist 字典。类型不匹配

Iterating over .plist dict. Type mismatch

我正在尝试迭代 plist 文件中的嵌套字典。问题是分解内容时类型不匹配。我总是收到 NSObject、NSDict 和其他 NSstuff 无法转换为 String 变量的错误,包括当我使用“(值)”、string() 时......如何将 plist 字典子集元组分解?(数组)到单独的变量中?

func LoadPlistContacts() {
    let path = NSBundle.mainBundle().pathForResource("ContactList", ofType: "plist")
    var AppContactsList = NSDictionary(contentsOfFile: path!)
    ListKeys = sorted(AppContactsList!.allKeys as! [String])

    for key in ListKeys {
        var (AppPersonName, AppPersonSurname, AppPersonCompany, AppPersonPhone) = AppContactsList[key]
        }

    }

更新: 我用字典而不是数组更改了 plist 并更新了代码,但类型不匹配仍然存在。正如 Airspeed Velocitynhgrif 在评论中指出的那样,更新后的 plist 示例确实变得更加混乱。如果带有注释错误的行不能解决问题,我是否应该嵌套循环?谢谢

var ListKeys: [String]!
var ListContacts: [String: String]!

func LoadPlistContacts() {

    if let path = NSBundle.mainBundle().pathForResource("ContactList", ofType: "plist") {
        var AppContactsList = NSDictionary(contentsOfFile: path)
        ListKeys = sorted(AppContactsList!.allKeys as! [String])
        ListContacts = sorted(AppContactsList!.allValues as [String:String]) { [=11=].0 < .0 }
        // I get an error [AnyObject] is not convertible to '[String:String]'

        for contact in ListContacts {

            let name =    contact["Forename"] ?? ""
            let surname = contact["Surname"] ?? ""
            let address = contact["Company"] ?? ""
            let phone =   contact["Phone"] ?? ""
        }

    }
    else {
        fatalError("Could not open Contacts plist")
    }
}

顺便说一句,Airspeed Velocity,喜欢你的博客!

Swift 不允许您像这样将数组解构为元组——主要是因为它不能保证有效(数组可能没有正确的条目数)。

您可能会发现在 plist 中有另一个字典比数组更容易:

然后像这样使用这些条目:

if let path = NSBundle.mainBundle().pathForResource("ContactList", ofType: "plist"),
    contacts = NSDictionary(contentsOfFile: path) as? [String:[[String:String]]]
{
    let sortedContacts = sorted(contacts) { lhs,rhs in lhs.0 < rhs.0 }

    // destructuring works here because contacts is known
    // at compile time to be an array of (key,value) pairs
    for (section, contactArray) in sortedContacts {
        for contact in contactArray {
            let name = contact["Forename"]
            let surname =  contact["Surname"]
            let address =  contact["Company"]
            let phone =  contact["Phone"]
            println(name,surname,address,phone)
        }   
    }
}
else {
    fatalError("Could not open Contacts plist")
}

请注意,当您取出这些条目时,它们将是可选的。这确实是这种方法的另一个好处——这意味着您可以省略 plist 中的条目,然后默认它们:

// default to blank string for phone number
let phone =   contact["Phone"] ?? ""

或授权他们:

    for (section, contactArray) in contacts {
      for contact in contactArray {
        if let name =    contact["Forename"],
               surname = contact["Surname"],
               address = contact["Company"],
               phone =   contact["Phone"]
        {
            println(name,surname,address,phone)
        }
        else {
            fatalError("Missing entry for \(section)")
        }
      }
    }

请注意,使用 if let 比使用 ! 强制解包更可取,即使您使用的是在构建时配置的 plist 之类的东西因此理论上永远不应该包含无效条目——因为这样,您可以进行明确的错误处理,如果您不小心将错误的数据放入 plist 中,这将有助于调试。