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 trialJeff Ripke
41,989 PointsLost on this question. How do I create a failable Init?
Not sure where to go with this question.
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) {
}
}
5 Answers
Stefan Cimander
37,115 PointsYou are getting close. The dictionary parameter is correct, as well as the guard statement. However, you still need to initialize the book properties. So far you asked the dictionary for the different Strings, but did not use them for initialization.
Think of the guard statement as an early exit from the initializer method. If the necessary information can not retrieved from the dictionary, the guard statement ensures, that the initializer returns nil. But otherwise, all book properties have to be initialized by the end of the method.
This said, make sure to assign the values retrieved from the dictionary to the book properties. Do not return nil outside of the guard statement a second time.
As a reminder, take this as an example for initializing the author property:
self.author = author
Stefan Cimander
37,115 PointsI think this challenge is hard, too. The failable initializer could be implemented with the help of a guard statement.
But first things first. Instead of a list of four different (optional) strings, the parameter of the initializer should be of type [String: String] and named dict. Next, you can use the provided keys to retrieve the individual values for the different properties.
All values that are retrieved from the dictionary are of type Optional(String), but two struct properties are of type String. These two are good candidates to check for existence with the help of a guard statement. If the dictionary does not contain all the values needed, a failable initializer should return nil.
I hope this helps. Please ask again, if you still have questions.
andrew naeve
11,503 Pointsstuck on this as well. why doesn't this work:
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
}
let price = dict["price"], pubDate = dict["pubDate"]
return nil
}
}
andrew naeve
11,503 Pointsgot it! and understand it a little better now too. in another post i found an answer using if statements but this seems way better.
Jakob Hansen
13,746 PointsI did the challenge, but I don't understand why the init method only accepts one arguement when we have 4 properties to be set. When trying to create an instance of the Book struct, we can only set one property, and it returns nil because the other properties are empty, yes?
let someBook = Book(dict: ["title":"potter"]) // prints nil in the playground
How can I add more to the someBook, to make it return all properties with values?
Stefan Cimander
37,115 PointsYou are right when saying that the init method accepts only one parameter, namely the dictionary. However this dictionary can contain a lot of key-value pairs instead of only the title. For experimenting in a playground you might want to use the following dictionary as parameter:
let potterDictionary = ["title": "Harry Potter", "author": "J. K. Rowling", "price": "29.95", "pubDate": "Jan 31, 2007"]
let someBook = Book(dict: potterDictionary)
Hope this helps :)