Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialCaleb Kleveter
Treehouse Moderator 37,862 PointsLoading files from a directory code challenge.
I am attempting to finish the loading files from a directory code challenge. Here are the instructions:
'Given a resource named "CrazyInformation.plist" located in the main application directory, first retrieve the path to this resource and assign the string to a constant named plistPath. Once you have the plistPath, create an instance of NSDictionary containing the contents of the plist.'
But I get this error on the second constant:
Bummer! Don't forget to instantiate the dictionary with the contents of the plist!.
This is the error in the preview:
swift_lint.swift:8:47: error: value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?
let dictionary = NSDictionary(contentsOfFile: plistPath)
^
!
import Foundation
// Add your code below
let plistPath = NSBundle.mainBundle().pathForResource("CrazyInformation", ofType: "plist")
let dictionary = NSDictionary(contentsOfFile: plistPath)
1 Answer
Michael Hulet
47,913 PointsTL;DR: pathForResource:ofType:
returns an optional, and you need to unwrap it.
The problem here lies in Swift's love of over-safety. It has a concept of "Optionals", where a variable could either contain a value or nil
. To find out, you have to "unwrap" it. This could be done in one of two ways.
The Easy Way
The fastest is to explicitly unwrap it is inline with an exclamation point. Be careful, though, as if it actually does contain nil
, your app will crash. It's probably ok in this case, since it should never be nil
, but you should form a habit of using the other way, which I'll show you in a second. In the meantime, explicitly unwrapping it would make your code look like this:
// This constant is inferred to be a String? (an optional String)
let plistPath = NSBundle.mainBundle().pathForResource("CrazyInformation", ofType: "plist")
// Notice the ! after plistPath. This unwraps the optional to get to the value inside
let dictionary = NSDictionary(contentsOfFile: plistPath!)
The Better Way
There's a better way to do this, though. That would be to implicitly unwrap it, which is known as "if let
" syntax. This is better because it's safer. If the value contains nil
, your app won't crash, and you can run some alternate code, instead. Using if let
syntax extracts the value out of the optional and assigns it to its own temporary constant which is only available within the scope of the if let
statement. Implicitly unwrapping it would look like this:
// This constant is inferred to be a String? (an optional String)
let plistPath = NSBundle.mainBundle().pathForResource("CrazyInformation", ofType: "plist")
// This will extract the String value from the optional and assign it to path
if let path = plistPath{
let dictionary = NSDictionary(contentsOfFile: path)
}
Caleb Kleveter
Treehouse Moderator 37,862 PointsCaleb Kleveter
Treehouse Moderator 37,862 PointsNeither of the code snippets are passing. I am getting the error
Bummer! Store the path to the resource in a constant named plistPath
. I tried to change some stuff to fix it, but nothing worked.Michael Hulet
47,913 PointsMichael Hulet
47,913 PointsI didn't test the snippet I posted in my actual answer, but a slightly adapted version of "The Better Way" seems to work. The only difference is that it shoves the creation of the
plistPath
constant into theif let
statement, and gets rid of the extraneouspath
constant entirely. Try this:Caleb Kleveter
Treehouse Moderator 37,862 PointsCaleb Kleveter
Treehouse Moderator 37,862 PointsThat did it! Thanks!