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 trial

iOS Build a Playlist Browser with Swift Building the Music Library and Playlist Models Struct Initialization

Paulo Braga
Paulo Braga
5,381 Points

Why use "as" in "title = playlistDictionary["title"] as String!"?

I've completed all the steps on Swift track and had no explanation about this syntax: title = playlistDictionary["title"] as String! ?

I do undestand we user this to get the value inside "title" dictionary as a String, but what I don't get it is why should we do that considering that the value for the "title" key is already a string!!

Could someone solve this doubt for me?

2 Answers

When we use dictionaries in Swift, we can add any object and on default, the type AnyObject is used as the type for our dictionary values. AnyObject is the top level object that represents the most basic object in Swift, but it does not provide all the additional functionality we may need if we are working with a String, Array, Int, and so on. In cases where our program may not know what type of object we are dealing with, we need to downcast it to the proper type using the as keyword:

// Downcast
var title = playlistDictionary["title"] as String!

We could define our dictionary a head of time:

var playlistDictionary = [String: String]()

In the above case, Swift would already cast the key/values of the dictionary to their proper types and there would be no need for downcasting. However, what would happen if our playlistDictionary could not only contain String values, but also Int values? In this case we have to initially have our dictionary contain AnyObject key/values and then we would have to downcast them to let Swift know what types we are dealing with and hence the need to use the as keyword.

Simply put, the need to downcast is a result of the tutor making the properties in the playlistDictionary optional (By adding the ? to the end did this).

This means that the index pointed to in the playlistDictionary does not store the string, but an object containing either the string or the nil value.

In order to get the string OR the nil value out again, we must use the bang (!) syntax to get the right type returned.

In this case, playlistDictionary["title"] as String! means that we are expecting a String value, but if the "title" was not set (if we failed to get this data from the web, for example) it would return a nil. If we used just 'as String' and the title returned nil, the app would crash.

TLDR: Use of (!) extrapolates the values from optionals (?) and can be equal to any type (Int, String etc) or the nil value. Consider the following:

var a: String = "Hello" // Fine.
var b: String? // Will work as it is an optional (?)
var x: String // Won't work as compiler sees it hasn't been (and won't be) initialised


// Using variable a, which is of type String and has been initialised
var c: String = a as String // Works Fine, but is unnecessary as type of a is same as c
var d: String = a  // Also works fine

var e = b  // This means b is now equal to {some: nil}, let's fix that
var f = b as String! // OK, so f is now equal to nil, to get rid of the pesky {some:_} we use (!)

// Common error: Explicitly declaring type on optional assigned variables / constants

// Comment the next line out when testing as playground will halt on this as an error!!
var g: String = b as String! // Won't work as g is explicitly declared as a String and won't accept type Nil

// A great example

var opt: String? // Currently {some: nil}

var iAmNil = opt as String! // value is nil

opt = "Stringy String" // Initialised opt
var iAmString = opt as String! // value is now "Stringy String"

Lob that in a playground and see what happens when you remove ! or ?

Thank you for the answers guys. @Sean, I'm a little confused about your statement: "In this case, playlistDictionary["title"] as String! means that we are expecting a String value, but if the "title" was not set (if we failed to get this data from the web, for example) it would return a nil. If we used just 'as String' and the title returned nil, the app would crash." I understand from above explanation that the reason to include "!" is to specify the String type, when you know that there will be absolutely a string coming in. But what is the advantage of having that?