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 Build a Simple iPhone App with Swift Getting Started with iOS Development Swift Recap Part 1

Alex Souto-Maior
seal-mask
.a{fill-rule:evenodd;}techdegree
Alex Souto-Maior
iOS Development Techdegree Student 4,909 Points

Why is this code working in Playground but not passing the code challenge in Treehouse?

In the "Swift Recap Part 1 “, I get through Task 1 OK but then on Task 2 I’m entering the following code. It works fine and is bug-free in Playground but is not passing the code challenge in Treehouse. When I click on Preview to see what the problem is I get an empty “Output.html” screen.

structs.swift
struct Tag {
  let name: String
}

struct Post {

    var title: String
    var author: String
    var tag: Tag

    init(title: String, author: String, tag: String) {
        self.title = title
        self.author = author
        self.tag = Tag(name: tag)
    }

    func description() -> String {
        return "\(title) by \(author). Filed under \(tag.name)"
    }

}

let firstPost = Post(title: "isoDevelopment", author: "Apple", tag: "swift")

let postDescription = firstPost.description()

6 Answers

Pasan Premaratne
STAFF
Pasan Premaratne
Treehouse Teacher

Hey Alex Souto-Maior

Your solution works perfectly fine on my end with no changes to the custom init method. I'm not entirely sure why it's not working for you.

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

Never mind. I figured out why it's breaking only on task 2. Your custom initializer does break the code challenge and that's because of how init methods work with structs.

When you write an initializer in a struct declaration (as opposed to an extension of the struct) you override the memberwise initializer automatically generated. This means that the code challenge doesn't know how to create an instance of your Post struct.

Yes, your initializer makes it easier to just pass in the string, but if we allow custom initializers, we have to anticipate every possible version of a custom initializer and guess at how to create an instance.

For example another student can do this

init() {
    self.title = "iosDevelopment"
    self.author = "Apple"
    self.tag = Tag(name: "swift")
}

This is also a valid initializer but again I have no way of anticipating this and using it to create an instance in the challenge test logic.

Typically in real world code the way I would write it is to leave the default memberwise initializer and create a convenience initializer in an extension of Post like so:

struct Tag {
    let name: String
}

struct Post {

    var title: String
    var author: String
    var tag: Tag

    func description() -> String {
        return "\(title) by \(author). Filed under \(tag.name)"
    }

}

extension Post {
    init(title: String, author: String, tag: String) {
        self.title = title
        self.author = author
        self.tag = Tag(name: tag)
    }
}

let firstPost = Post(title: "isoDevelopment", author: "Apple", tag: "swift")
let secondPost = Post(title: "iOSDevelopment", author: "Apple", tag: Tag(name: "swift"))

Since the initializer is in an extension, you don't override the memberwise default. This allows me to use the default initializer to create an instance and check your function, but it also allows you to use your convenience init. Note that both initializers can be used as shown above.

Hope this helps understand why it would be impossible for us to allow custom inits as default

Kristof Kocsis
Kristof Kocsis
15,455 Points

Your code is fine but I think that with the custom init method you confuse the system. You should try:

  1. remove init
  2. create the instance like:
let firstPost = Post(title: "IOSDev", author: "Me", tag: Tag(name: "HAHA"))
Alex Souto-Maior
seal-mask
.a{fill-rule:evenodd;}techdegree
Alex Souto-Maior
iOS Development Techdegree Student 4,909 Points

Thanks for this, Kristof. You're right. I had noticed that this would do the trick. But I don't understand why this custom init should break the system.

As far as I can see, the custom init is a much better solution in this case because it makes for a more usable experience for entering the parameters when creating an instance of the Post struct. Which is the type of thing that Pasan has been advocating throughout his videos so far.

Kristof Kocsis
Kristof Kocsis
15,455 Points

I agree, your solution with the custom init method is much more readable, and if you would write this code in real life for real people this would be the way to go. But since you are writing this code for a machine and an automated test you should stay simple and only do what is necessary.

Alex Souto-Maior
seal-mask
.a{fill-rule:evenodd;}techdegree
Alex Souto-Maior
iOS Development Techdegree Student 4,909 Points

Hey Pasan,

Thanks a lot for taking the time to look into this and for explaining it so well! I now get the problems with allowing custom inits in the challenge test.

I didn't know about extensions and just did a quick read up on it in the Apple documentation (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html#//apple_ref/doc/uid/TP40014097-CH24-ID151) after seeing your solution above.

So I have two more quick questions for you. (1) Is it generally a better practice to not create custom inits for structs, and to use extensions instead? Or was it only more justified in this case because of the limitations in checking the challenge test? (2) Will we be learning more about extensions further into the Techdegree program?

Thanks again!

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

No problem!

I find it a better practice to create my custom inits for structs in the extension purely so that it doesn't override the memberwise init.

The Intermediate Swift 3 course (should be out in a week) covers everything you need to know about extensions.