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 Enumerations and Optionals in Swift Introduction to Optionals Initializing Optional Values

Martel Storm
Martel Storm
4,157 Points

initializing optional layers Code Challenge

Sorry my life and code is a mess. Can someone provide the answer and explain a bit?

optionals.swift
struct Book {
    let title: String
    let author: String
    let price: String?
    let pubDate: String?

    init? (dict: [String : String]) {
        guard let Book = title ["title"], let author = ["author"],
        else {
            return nil}
       let price = bookPrice ["price"]
        return Book(dict)
    }
}

1 Answer

Dan Lindsay
Dan Lindsay
39,611 Points

Hey Martel,

To help with understanding, first look at how we do an init method for a class that has no optional properties:

class BookNoOptionals {
    let title: String
    let author: String
    let price: String
    let pubDate: String

    init(title: String, author: String, price: String, pubDate: String) {
        self.title = title
        self.author = author
        self.price = price
        self.pubDate = pubDate
     }
}

When we say self.title, we are basically referring to the let title: String property of our class. We then assign that to our title parameter of our init method. However, when one or more of our original properties is an Optional, we need to use a failable initializer, as we may not have to use those properties. You have the guard statement almost correct(you have the author part right, but should have title instead of Book), but we still need to assign the properties of our struct(using self) to the properties in our initializer. So here is the updated book struct:

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.title refers to our let title: String, and we assign the value of title from our guard statement to it
        self.author = author
        self.price = dict[price]  // if someone decides to add this key to our dict, we assign it’s value to our let price: String? property 
        self.pubDate = dict[pubDate]
        }
}

So we now could create a book with just a title and author, like this:

let myBook = Book(dict: ["title": "The Blood Mirror", "author": "Brent Weeks"])

or we can add one or both of the other properties that are optional, like this:

let myBookWithPrice = Book(dict: ["title": "The Blood Mirror", "author": "Brent Weeks", "price": "21.99"])

or this

let myBookWithPriceAndPubDate = Book(dict: ["title": "The Blood Mirror", "author": "Brent Weeks", "price": "21.99", "pubDate": "2016"])

Now we can access those properties with dot notation.

myBook?.author \\ this will give us Brent Weeks

Hope this helped!

Dan

Martel Storm
Martel Storm
4,157 Points

Thank you for taking the time to provide shut a clear and helpful response!