2015-04-12 57 views
1

我想从plist文件迭代嵌套的字典。问题在于分解内容时类型不匹配。我总是得到错误,NSObject,NSDict和其他NSstuff不能转换为字符串变量,包括当我使用“(价值)”,字符串(),作为..如何分解一个plist字典sub set tuple?(array)into separate variables ?迭代.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中和更新的代码,但类型不匹配仍然存在。 As Airspeed Velocity and nhgrif在评论中指出,例子确实与更新的plist有关。如果具有注释错误的行不能解决它,我应该嵌套循环吗?谢谢。

enter image description here

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]) { $0.0 < $1.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") 
    } 
} 

顺便说一句,空速速度,爱你的博客!

回答

4

Swift不允许你像这样将数组解析为元组 - 主要是因为它不能保证工作(数组可能没有正确数目的条目)。

您可能会发现更容易,而不是阵列,拥有的plist内的另一个字典:

A plist of dictionaries inside arrays inside dictionaries

然后使用像这样的条目:

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中。

+0

我正在研究一个答案,但你很好涵盖了所有要点。只是要评论说,提问者的plist结构并不符合你的说法。它看起来更像这样:http://i.imgur.com/W03yayM.png – nhgrif

+0

啊,真的,好点。代码应该很容易适应,否则将是一个更加混乱的例子。 –

+0

排序封闭测试中的.0访问器是什么?为什么它是必需的? –