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 trialandrew naeve
11,503 Pointsok, i used the ! operator and shouldn't have..
I used the bang operator to solve this and know I should't have.. but am at a loss as to how to approach this without doing it. any pointers?
struct Book {
let title: String
let author: String
let price: String?
let pubDate: String?
init?(dict: [String: String]){
self.title = dict["title"]!
self.author = dict["author"]!
self.price = dict["price"]
self.pubDate = dict["pubDate"]
}
}
2 Answers
Danny Yassine
9,136 PointsLooking at your Struct, you are saying that a Book must have a Title and author, but price and pubDate are of Optional type, thus these two properties don't need to be initializes with a value when you are initializing/creating your Struct.
For title and author properties, when beeing initialized, the value being passed to them must be true and "not-nil". Thats why you had to put the bang operator when accessing your dictionary for "title" and "author". If a value of nil was to come from the dictionary, it would create a run-time error. Since swift can detect that, you had to pit "!" to remove the error.
For price and pubDate properties, if the value in the dictionary for "price" and "pubDate" are nil, thats ok, because those two properties are optionals and they can be nil. Thats why you don't need the bang operator for them.
So its also up to you on how you want to build your models if some properties will be optionals or not.
here's the link for the Optionals in the Swift Programming Book, Look for the OPTIONALS header:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID330
miikis
44,957 PointsHey Andrew,
I'm finding it difficult to elucidate exactly why force unwrapping an Optional is so "bad" so maybe Pasan Premaratne can add some words here. Nonetheless, here is one way to create this Struct without force unwrapping each non-Optional:
struct Book {
let title: String
let author: String
let price: String?
let pubDate: String?
init?(dict: [String: String]) {
guard let title = dict["title"], let author = dict["author"] else {
return nil
}
self.title = title
self.author = author
self.price = dict["price"]
self.pubDate = dict["pubDate"]
}
}
Pasan Premaratne
Treehouse TeacherIn this instance, your data to initialize Book is obtained from a dictionary that you pass in when creating the struct. Let's say this dictionary is something that you get by hitting a 3rd party web service. There is no way to guarantee that the response dictionary will always contain the values you're expecting (the API may change, your connection may drop resulting in incomplete data, etc). Let's assume 90% of the time the data is correct but 10% of the time the author key is missing for some books. In that 10% case, this line of code
self.author = dict["author"]!
will cause the app to crash completely with no information provided to the user. So rather than being safe, the !
operator does the exact opposite and creates unsafe code. The Swift team named it the force unwrap operator to indicate that you are working against the goal of safety and forcing your code to do something it really shouldnt.
miikis
44,957 PointsAwesome Pasan! Thanks for clearing that up. I was trying to explain but my brain wouldn't cooperate; I kept typing and deleting and typing and deleting...
andrew naeve
11,503 Pointsandrew naeve
11,503 PointsThanks Danny, that helps a lot!