Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary access in Swift

Consider the following code which gets an array of dictionaries from a plist:

let path = NSBundle.mainBundle().pathForResource("books", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path)
let books:Array = dict.objectForKey("Books") as Array<Dictionary<String, AnyObject>> //I hate how ugly and specific this is. There has got to be a better way??? Why can't I just say let books:Array = dict.objectForKey("Books")?

let rnd = Int(arc4random_uniform((UInt32(books.count))))
let bookData:Dictionary = books[rnd]

Now, I'm having trouble accessing individual book dictionaries:

let title:String = bookData.objectForKey("title") //[String: AnyObject] does not have a member named 'objectForKey'

let title:String = bookData["title"] // (String, AnyObject) is not convertible to String 

What is the proper way to find the title of the book?

like image 857
soleil Avatar asked Jul 11 '14 19:07

soleil


People also ask

How does dictionary work in Swift?

Swift 4 dictionaries use unique identifier known as a key to store a value which later can be referenced and looked up through the same key. Unlike items in an array, items in a dictionary do not have a specified order. You can use a dictionary when you need to look up values based on their identifiers.

Is a dictionary a sequence Swift?

Dictionaries in Swift and Objctive-C are unordered collections. They do not have any native order. If you want your data to be stored in a specific order, use an array of some other objects.


1 Answers

You could use the new syntactic sugars for Arrays and Dictionaries from Beta 3.

let path = NSBundle.mainBundle().pathForResource("books", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path)
let books = dict.objectForKey("Books")! as [[String:AnyObject]]

You can access bookData as is, automatic type inference should work...

let rnd = Int(arc4random_uniform((UInt32(books.count))))
let bookData = books[rnd]

Put an explicit type for each item in the book dictionary, since we have defined it as AnyObject.

let title = bookData["title"]! as String
let numPages = bookData["pages"]! as Int

Late edit

  • With the nil coalescing operator ?? you can check for nil values and provide an alternate value like so:

    let title = (bookData["title"] as? String) ?? "untitled"
    let numPages = (bookData["pages"] as? Int) ?? -1
    
like image 119
Benzi Avatar answered Oct 03 '22 11:10

Benzi