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 trialEugene Yan
3,896 PointsI am not sure where went wrong.
The task is: In the editor, you have a struct named Book which has few stored properties, two of which are optional.
Your task is to create a failable initializer that accepts a dictionary of type [String : String] as input and initializes all the stored properties. (Hint: A failable init method is one that can return nil and is written as init?).
Use the following keys to retrieve values from the dictionary: "title", "author", "price", "pubDate"
Error: Your code could not be compiled.
struct Book {
let title: String
let author: String
let price: String?
let pubDate: String?
init?(dictionary: [String: String]){
if let title = dictionary["title"], let author = dictionary["author"] {
self.title = title
self.author = author
} else {
return nil
}
self.price = dictionary["price"]
self.pubDate = dictionary["pubDate"]
}
}
6 Answers
miikis
44,957 PointsHi Eugene,
That Challenge doesn't want you to use the word "dictionary" as the name for the parameter. Try changing the parameter name to something like "dict" and you should be able to pass it. Also βeven though your current code will pass β consider using a guard statement as it really is the best option for this situation.
Jeff Ripke
41,989 PointsHaving a hard time figuring out how to use the guard statement in this failable init:
What am I doing wrong?
struct Book {
let title: String
let author: String
let price: String?
let pubDate: String?
init?(dict: [String: String]) {
guard let price = dict["price"], let pubDate = dict["pubDate"] else {
return nil
}
self.price = dict[price]
self.pubDate = dict[pubDate]
}
}
Matthew Connolly
iOS Development Techdegree Student 11,595 PointsRemember that you have to initialize all the properties in your struct
. Right now you are initializing only price
and pubDate
.
Also, for you guard statement, think about what properties of Book
are absolutely necessary to create an instance of Book
, those are the properties you want to "guard" against.
Do you need a price
and a pubDate
to create an instance?
miikis
44,957 PointsHey Jeff,
title and author β as opposed to price and pubDate β cannot be nil; they have to be Strings. The place where you would set these properties is inside that fail-able initializer. Basically, you want to return nil out of that initializer if either title or author turn out to be nil. Otherwise, you want to set title and author to their corresponding values from the dictionary. You should also set price and pubDate here but note that β because they're optional Strings β you can just set them directly (i.e., without an if-let or a guard-let etc.).
Jeff Ripke
41,989 PointsThanks for helping. I am still confused on how to do this. I created the guard statement for title and author but still getting errors.
init?(dict: [String: String], price: String, pubDate: String) {
guard let title = dict["title"], let author = dict["author"] else {
return nil
}
self.price = price
self.pubDate = pubDate
}
Matthew Connolly
iOS Development Techdegree Student 11,595 PointsHey Jeff
Your guard
statement looks much better, great job! That's exactly how you want to implement it.
Now you have to finish initializing. Think about how the init?
is going to work. If you pass the guard
statement (e.g. your title
and author
are not nil
) you will move onto initializing the Book
instance. Currently, you are only initializing with self.price
and self.pubDate
.
I would also adjust your parameters to only include a dictionary like below and reference the price
and pubDate
within the function:
init? (dict: [String : String]) {
/* guard statement */
self.title = /*insert code*/
self. author = /*insert code*/
self.price = dict["price"]
self.pubDate = dict["pubDate"]
}
Jeff Ripke
41,989 PointsThanks that makes since now, I was think the guard statement was the init.
Matthew Connolly
iOS Development Techdegree Student 11,595 PointsI did the same thing initially. Happy coding!
Sayuri Katz
6,148 Pointsstruct Book { let title: String let author: String let price: String? let pubDate: String?
init?(dict: [String: String], price: String, pubDate: 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"]
}
}
Make sure you are creating a failable initializer that accepts a dictionary as an argument for initialization
Alen Kirm
7,632 PointsWell, that was very challenging. Thank you Matthew and Jeff for help.
The solution for this challenge is:
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 TeacherPasan Premaratne
Treehouse TeacherHey Eugene,
The directions should have said use
dict
as your initializer argument name. Sorry for the confusion, I've modified the directions!