Initializers in Swift

      No Comments on Initializers in Swift

In Swift you'll be constructing objects all the time. It might seem simple at first glance but initializers in Swift are a pretty deep topic.In Swift you’ll be constructing objects all the time. It might seem simple at first glance but initializers in Swift are a pretty deep topic. In this article we’ll cover designated and convenience initializers. We’ll touch a bit on the failable initializers, required initializers and initializers in structs. We’ll finish with a deinit 🙂

Initialization

Initialization is a process of preparing your class (or struct) for use. Swift is a bit strict on initialization. All your properties have to be initialized in order for you to use the class (there are some exceptions to this, we’ll cover them later).

When you define your class and your variables, you can assign default values to your variables, if that makes sense to you. Or you can use the initializer to set the values of your properties. For example, you could set default values for your properties like this:

If you provide default values for all the non-optional properties you will get this default initializer for free. Another way to initialize your properties is to create your own initializer:

Optional Properties

The properties you don’t have to initialize are optional properties. It kinda makes sense when you think about it, because they can be nil anyway. If you added an optional property to our example above, your code would compile just fine:

The same applies to implicitly unwrapped optional properties. If we were to make the ‘story’ property of ‘String!’ type the code would still compile.

Constant Properties

You can set your constant properties in the initializers, as you would expect:

You can set them only once, and a subclass can’t set the constant properties of its superclass.

Just a note on setting the properties. If you’re setting your properties directly or in an initializer your property observers won’t get called.

Designated Initializers and Convenience Initializers

If you don’t provide all the default values for your properties you must have an initializer or your code won’t compile. In swift we have multiple types of initializers. Designated initializer is an initializer that  initializes all the non-optional properties. You must have at least one designated initializer. From the example above, we created a designated initializer:

Another type of initializer is a convenience initializer. You create a convenience initializer by adding a keyword ‘convenience’ in front of it. Convenience initializer must call a designated initializer. Or it can call another convenience initializer, as long as the last convenience initializer in the chain calls the designated initializer. Let’s see an example of a convenience initializer:

Inheritance and Initializers

For classes, initializers get a bit more interesting. Convenience initializers can only call other initializers within the same class, they can’t call the superclass initializers. Only designated initializers can call the superclass initializers. There’s a great graphic from Apple that illustrates this:

Source: apple.com

Subclasses don’t inherit a superclasses’ initializers. So you will have to provide overrides yourself. There are two cases where your subclass will automatically inherit the superclass initializers: If you provide all the default values for the properties, or if you implement all of the superclasses designated initializers. For example:

Here we added a new property, we don’t have a default value, and we’re overriding a designated initializer of our superclass. We can see that we can use the superclass convenience initializer when creating an instance of the ‘DigitalMovie’ class.

Required Initializers

If you want every subclass to implement a certain initializer, just mark it with the ‘required’ keyword. For example:

We have a required initializer in the ‘Movie’ class and we had to implement it in our ‘DigitalMovie’ class as well.

Failable Initializers

When you’re creating your objects, maybe you don’t have all the data that you need, or some of it is invalid. What ever your case is, you have an option to abort object initialization. You can easily do this with a failable initializer. Failable initializers have a question mark after the init keyword, you must have seen it all around the place. You can fail at any time during the initialization by returning nil. Technically speaking, swift initializers don’t return a value (unlike objective-c). Let’s see a quick example of a failable initializer:

We’re checking for a year here, and if it’s less than 1900 we fail the initialization. Notice how ‘aMovie’ property is now an optional type.

This initializer will create an optional instance of a ‘Movie’ type. You could also define your initializer to return an implicitly unwrapped instance of a ‘Movie’ type by using the exclamation mark operator:

Throwable Initializers

Another type of a failable initializer is a throwable initializer. Perhaps for your use case it would make more sense to throw an error. Especially if you want to provide a bit more details about why the initialization failed. We can modify our example a bit so it would throw an error:

I won’t go into details about error handling in swift, because it’s a topic on its own. You can see from the example that you’re getting a lot more details now when your initialization fails.

Memberwise Initializers in Structs

These initializers are specific for structures. If you don’t define your custom initializers in structs you get a free initializer that will take in all the properties of the struct as parameters and initialize it. Let’s change our example a bit to see this in action:

You will get this free initializer even if you provide default values for your properties, unless one of your properties is a constant, then you get nothing 🙂

Deinitializers

What better way to end a post than with a deinit 🙂 Deinitializers are quite simple. They are methods that take no parameters and will be called just before your class is deallocated, they are available only on class types. You can use them to perform your final cleanups before your class is destroyed. For example, you can remove yourself as an observer if you registered for notifications. You can’t call deinit directly, and your superclass deinit is called just before your own deinit implementation returns. Let’s see this on a quick example:

Here we can see that our deinit is being called first, and then the super deinit is being called automatically.

Conclusion

Object construction might seem like a simple topic, but it can be quite complex. There are quite a few rules to follow in swift, but once you understand them you’ll have no problems. In this article we covered the basics, and I hope I shed some light on object construction (and destruction) in swift.

Have a nice day 🙂

Dejan.

More resources

1+

Leave a Reply