Jakob Hansen Jakob Hansen - 4 months ago 18
Swift Question

instance of a failable init method

This is my code:

struct Book{
let title: String
let author: String
let price: String?
let pubDate: String?

init?(title: String, author: String, price: String, pubDate: String){
guard let title = title, let author = author else { // error here
return nil
}

self.title = title
self.author = author
self.price = price
self.pubDate = pubDate
}


}

My error says Initializer for conditional binding must have Option type not 'String'
My question is, why do I get this error, if I understand the guard statement correctly, I should only pass in the non-Optional properties before the else, and after the braces, the optional ones, like I've done here.

Answer

I would suggest you forego the failable init altogether. Your structure holds a title and author which are not Optional, so make your initializer reflect that. Don't let them try to create a book unless they can provide a title and and author.

The other two properties are Optional. I suggest you provide default values of nil in the initializer for those, which gives your user the most flexibility in creating a Book:

struct Book {
    let title: String
    let author: String
    let price: String?
    let pubDate: String?

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

let book1 = Book(title: "The Hitchhiker's Guide to the Galaxy", author: "Douglas Adams")
let book2 = Book(title: "The Shining", author: "Stephen King", price: "20.00")
let book3 = Book(title: "Little Women", author: "Louisa May Alcott", price: "15.99", pubDate: "1868")
let book4 = Book(title: "Harry Potter", author: "J. K. Rowling", pubDate: "1997")

If you really want to be able to pass in nil for anything, but fail if they don't provide a title and an author, then use guard to unwrap title and author, otherwise fail and return nil:

init?(title: String? = nil, author: String? = nil, price: String? = nil, pubDate: String? = nil) {
    guard let title = title, author = author else { return nil }
    self.title = title
    self.author = author
    self.price = price
    self.pubDate = pubDate
}

// These all return nil
let book5 = Book()
let book6 = Book(title: "War and Peace")
let book7 = Book(author: "Ray Bradbury")
let book8 = Book(title: "Pride and Prejudice", price: "40.00", pubDate: "1813")
Comments