Search code examples
iosswiftdictionaryplist

using key : value after loading dictionary from a plist using swift


I'm using Xcode 6 with Swift.

When I create a dictionary programmatically, I can print out by key or value or create arrays. When I create and load a dictionary from a plist, I can print the plist in total, but can't create arrays or print either the keys or values. The error message is 'NSDictionary?' does not have a member named 'values'.

I notice the programmatic dictionary is printed inside brackets with a colon between key and value, but the plist loaded dictionary is printed inside braces with = signs between the key and value. I assume this may be the problem, but don't know why it formatted this way or how to fix it.

 //  Programmatic Dictionary Code
        var newDict:[String:String] = ["car":"ground", "airplane":"sky", "boat":"water"]

    println("newDict key:value are: \(newDict)")

    //Prints Out as expected
    newDict key:value are: [car: ground, boat: water, airplane: sky]



     // plist read to Dictionary Code
     var type : NSDictionary?

     if let path = NSBundle.mainBundle().pathForResource("transport", ofType:     "plist")   {
     type = NSDictionary(contentsOfFile:path)
     }

     println(type)

    // print out isn't the same as above
    Optional({
        airplane = sky;
        boat = water;
        car = ground;
     })

Trying to access the key or the element in this loaded dictionary returns an error message indicating the dictionary doesn't have a member ....

I've been unable to find anything to explain why the loaded dictionary would be different or how to access the members.


Solution

  • You need to unwrap your optionals. An optional is a variable that can hold a value just like any other variable, but it can also hold no value at all, or nil.

    This code:

    var type : NSDictionary?
    
    if let path = NSBundle.mainBundle().pathForResource("transport", ofType:     "plist")   {
         type = NSDictionary(contentsOfFile:path)
    }
    
    println(type)
    

    should be:

    var type : NSDictionary?
    
    if let path = NSBundle.mainBundle().pathForResource("transport", ofType:     "plist")   {
         type = NSDictionary(contentsOfFile:path)
    }
    
    println(type!)
    

    Anytime you use type (or any other optional), you need to unwrap it with !, ?, or if let.

    Note that if type contained nil and you unwrap it with !, your app will crash, saying "unexpectedly found nil while unwrapping optional value".

    For more information about optionals, see The Swift Programming Language: The Basics.