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 trialIan Bowers
3,665 Pointscreating a Struct init?() and accepting a dictionary type
I am working on this problem:
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 as input an initializes all the stored properties. (Hint: A failable init method is one that can return nil and is written as init?). Name the initializer parameter dict.
Use the following keys to retrieve values from the dictionary: "title", "author", "price", "pubDate
struct Book {
let title: String
let author: String
let price: String?
let pubDate: String?```
init? (title: String, author: String, price: String?, pubDate: String?
init?(dict: [String:String])
init?(NSDictionary) ??
I've tried declaring each individual constant like up above and before that I basically copied
struct Friend {
let name: String
let age: String
let address: String?
}
func createFriend(dict: [String: String]) -> Friend? {
guard let name = dict["name"], age = dict["age"] else {
return nil
}
let address = dict["address"]
return Friend(name: name, age: age, address: address)
}
and it wouldn't compile
11 Answers
Evan Demaris
64,262 PointsHi Ian,
I think the Challenge is looking for something more like this;
struct Book {
let title: String
let author: String
let price: String?
let pubDate: String?
init?(dict: [String: String]){
guard let title = dict["title"], author = dict["author"] else {
return nil
}
self.title = title
self.author = author
self.price = dict["price"]
self.pubDate = dict["pubDate"]
}
}
Abdoulaye Diallo
15,863 Pointsstruct 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"]
}
}
kols
27,007 PointsActually Nick Mauro is correct (thanks, Nick!) — at this time (Swift 4) — the 'let' keyword is required each time with multiple/inline declarations in guard statements.
When the above code by Evan Demaris was provided, it was also correct, but now requires the addition of a second 'let' keyword to pass. (In this example, if you try removing the 'let' keyword before the 'author' declaration in the guard statement, you should receive a compiler error in Xcode.)
A further explanation is provided in the answers for this question on Stack Overflow.
Updated answer to this challenge shown below:
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"]
}
}
Ian Bowers
3,665 PointsI'm an idiot I don't know why I was forcing a return statement I was trying anything and everything to get it to work. Thanks!!
Nick Mauro
3,944 Pointswarp42 you and Even are missing a let
before author. Try:
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"]
}
}
Evan Demaris
64,262 PointsAs you are declaring multiple constants inline, the second let
is assumed.
Nick Mauro
3,944 PointsI believe that is no longer the case in Swift 3.
Nick Mauro
3,944 PointsI believe that is no longer the case in Swift 3.
Evan Demaris
64,262 PointsThis question was asked over a year ago regarding iOS > Swift 2.0 Enumerations and Optionals > Introduction to Optionals > Initializing Optional Values; Swift 3 syntax wouldn't be relevant in this context.
Tong Wang
4,800 Pointsstruct 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"] }
} There is no complier error here when I add "!" . I just wondering what might go wrong with this code?
Brian Habecke
2,287 PointsI keep getting a "your code could not be compiled, even by cutting and pasting the above example by Evan. When switching to the editor, no errors are shown. What gives?
Evan Demaris
64,262 PointsI'm not sure what's causing that problem; you're deleting the original code before pasting in mine, right?
warp42
3,171 PointsMaybe it's the formatting? Try the code below (I just successfully completed the test with this code...)
struct Book {
let title: String
let author: String
let price: String?
let pubDate: String?
init?(dict: [String: String]) {
guard let title = dict["title"], author = dict["author"] else {
return nil
}
self.title = title
self.author = author
self.price = dict["price"]
self.pubDate = dict["pubDate"]
}
}
(honestly, it looks identical though...)
justinm
10,385 PointsSometimes I get this issue if there is too many/not enough brackets. When you copy and paste the code try to make sure the brackets match up properly and that there isn't an extra one from the old code.
Brian Habecke
2,287 PointsI have no clue what happened there, but it looks like the browser wasn't resetting properly. Quit out yesterday, logged in again today, reposted the correct answer, it worked. Thanks for the help though!
Logan Cornelius
16,876 PointsI'm having a hard time understanding how this plays out in real case scenario. I'm setting these all up for a safe guarded initializer, but when I actually initialize the dictionary I only have the [String:String]. Getting a little confused over all this.
Luke Bearden
15,597 PointsLuke Bearden
15,597 Pointswhy do title and author need to be set before setting them to self.title and self.author? Why doesn't the following work?
Jesse DeOms
18,815 PointsJesse DeOms
18,815 PointsThanks Evan for your help with this (and thanks Ian for posting this question)! I was very close on my own and seeing your work here was really helpful :)
Edward Sapp
8,479 PointsEdward Sapp
8,479 PointsI'm confused--wouldn't this crash if there's no value for price & pubDate? Shouldn't you also protect those with an "if let" or a "guard" statement?
Evan Demaris
64,262 PointsEvan Demaris
64,262 PointsHi Edward,
price
andpubDate
are optional, as indicated by the question mark. Optionals can either have a value or be nil. Because the init needs to be failable, it too has a question mark, and handles the two non-optional properties using a guard statement.Hope that helps!
Evans Attafuah
18,277 PointsEvans Attafuah
18,277 Pointsswift 3.0 requires let for unwrapping multiple optionals
Josh Rondestvedt
3,830 PointsJosh Rondestvedt
3,830 Pointsin regards to the guard let title, add let before author.
Manas Vijaywargiya
12,598 PointsManas Vijaywargiya
12,598 Pointsadd let let author.....
kols
27,007 Pointskols
27,007 PointsThis code is correct except for a missing 'let' keyword before 'author' in the guard statement. (At this time [Swift 4], the 'let' keyword is required for use with multiple declarations in guard statements.)
See full code / answer below...