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

Michael Williams
PLUS
Michael Williams
Courses Plus Student 8,059 Points

Understanding Initializers better in Swift

Hi everyone:

I've been working my way through the Swift courses and have moved on to building a simple iPhone app portion. However, I still feel a little shaky on my understanding of init methods and why you need to use them. And I especially get confused when you throw in self.(insert property).

Could anyone explain this stuff like I'm five? I feel it's important to fully grasp this stuff so that I'm not just bumbling my way through code challenges. I've been reading Apple's dev documentation for Swift, which sometimes leaves me more confused than anything. And I also bought "Coding iPhone Apps For Kids," as I was hoping it would help explain things in a simpler manner. Sadly, some of its explanations aren't as simplified for a 10-year-old reading level... that or the 10-year-olds reading it are Mensa-level.

2 Answers

Arman Arutyunov
Arman Arutyunov
21,900 Points

Hi Michael,

You asked to explain why we need to use init methods like for a kid, so I'll try to do my best. Consider we have a class Person. This class might have some stored properties and some methods like this:

class Person {
    let firstName: String
    let lastName: String

    func getFullName() -> String {
        return firstName + " " + lastName
    }
}

We have to remember that a class is just a blueprint of what you will really want to use in your program - an instance of a class. Instance of a class is an object that you can use and work with because somehow its firstName and lastName have real values and its methods can return something meaningful. But to make all of it happen you have to initialize your class. To initialize you need an init method inside your class and some arguments you could use to give your stored properties some values. So you have to understand that init method is just a method that gives values from outside of your class to properties you didn't give yet. I hope you get that let firstName: String is a property without value. The compiler will know that it has a String type but it is not enough. To instanciate a class you have to init all of its stored properties. You can add another property with a value and you'll see that you don't need to initialize it inside init method because it already has its value. Like this

class Person {
    let firstName: String
    let lastName: String
    let greeting = "Hello, "

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }

    func getFullName() -> String {
        return firstName + " " + lastName
    }

    func greet() -> String {
        return greeting + getFullName()
    }
}

Then let's try to use our fully configured class outside in some other place:

class SomeViewController {

    @IBOutlet weak var titleLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        let michael = Person.init(firstName: "Michael", lastName: "Williams") 
        //you don't have to use init keyword here. 
        //compiler would get that you want to call init method only because you opened parentheses after class's name
        //you could easily write following
        //let michael = Person(firstName: "Michael", lastName: "Williams") withour init
        //and that would be much more appreciated in the community because it's 
        //cleaner and prettier. I used init. keyword only for you to easily get that
        //this is the same init() method from the Person class and we just call it from 
        //other class

        titleLabel.text = michael.greet()
    }
}

You can see that this class would not work if we didn't know firstName and lastName. In viewDidLoad() we init Person with some hardcoded values and they go to the init() method of Person class. Inside the init method we assign hadrcoded values we passed in viewDidLoad() to our stored properties.

Now let's talk about self. Names of stored properties and init method's arguments are the same. We have to use self keyword to differentiate class's properties from init method's arguments. If we use self. before some property, that means "this property (or method) belongs to the class (or struct) that you are working with right now".

Hope you get the part that self.firstName is the constant we declared in the top of our Person class - our stored property. And the firstName is the init method's argument. The last one has a value from outside and the first one with self. keyword has not. But we pass the value from argument to the property and that is a process of initialization. After we did that our class instance (constant michael in viewDidLoad()) now has all properties initialized and we can use all the methods it has.

I don't know if my explanations would be somewhat understandable for a kid but I hope I answered for some of your questions instead of confusing you more :)

Michael Williams
Michael Williams
Courses Plus Student 8,059 Points

Thank you for your thoughtful reply. So essentially, the class is the blueprint, but it can't build anything without some materials. So by initializing it, you're giving it some materials to build that thing. But why do you even need to use init? When they were writing Swift, why couldn't they make it easier on everyone and just let that automatically happen?

Two follow up questions

ONE: Why is it that some init methods don't have .self. in them?

TWO: Could you clarify this paragraph a little? I was a little confused by it:

Hope you get the part that self.firstName is the constant we declared in the top of our Person class - our stored property. And the firstName is the init method's argument. The last one has a value from outside and the first one with self. keyword has not. But we pass the value from argument to the property and that is a process of initialization. After we did that our class instance (constant michael in viewDidLoad()) now has all properties initialized and we can use all the methods it has.

Thanks again!

Arman Arutyunov
Arman Arutyunov
21,900 Points

I guess, in any language you'll see some sort of things like init methods in classes. The thing is as programmers we very often don't know what kind of data will be passed to the class because we don't put there hardcoded values. In most cases it's arrays of data form the web and we just use for in loops or .map operators that you don't need to worry about yet. The main idea is that Person class has two parts without value. And these two parts play an essential role in every method of the class. So basically you can't work with Person class not knowing its firstName and lastName variables. You have to assign it outside of the class when instantiating so the whole mechanism would work.

Answer for both ONE and TWO questions That's true. Sometimes you don't need to use self. keyword. We need to use it only if the names of the class's property is the same as the init method's argument. For example, we couldn't implement this kind of init method:

init(firstName: String, lastName: String) {
    firstName = firstName
    lastName = lastName
}

Because the compiler wouldn't get what you mean. For him you are assigning argument's value to that same argument. The self keyword helps us to differentiate them. Constant or variable with self keyword is always a property of a class. The one without self is the property of the init method scope in this case. You could easily hack it around and name arguments something like xFirstName and xLastName and you wouldn't need self anymore.

Michael Williams
PLUS
Michael Williams
Courses Plus Student 8,059 Points

Thank you for your clarification. That's what I needed to make it click into place.