What Is a Memberwise Initializer

Download Your Free Copy of
The Missing Manual
for Swift Development

The Guide I Wish I Had When I Started Out

Join 20,000+ Developers Learning About Swift Development

Download Your Free Copy

A memberwise initializer is an initializer that is automatically generated by the compiler for structs that don't define a custom initializer in their declaration. That sound complicated. Let me show you a few examples to explain this in more detail. Create an empty playground if you want to follow along.

We define a struct with name Book. The Book struct declares two constant properties of type String, title and author.

import Foundation

struct Book {

    let title: String
    let author: String

}

Because the Book struct doesn't define a custom initializer in its declaration, the compiler generates a memberwise initializer. Xcode confirms this when we try to initialize a Book struct. The list of suggestions Xcode displays include the memberwise initializer.

The compiler generates a memberwise initializer for structs.

Default Values

We only scratched the surface with the Book struct. Let's take a look at a more complex example. The ShoppingCart struct declares two variable properties, totalPrice of type Double and numberOfItems of type Int.

import Foundation

struct ShoppingCart {

    var totalPrice: Double
    var numberOfItems: Int

}

You know from the previous example that the compiler generates a memberwise initializer for the ShoppingCart struct. If we assign a default value to the properties, the options we have to create a ShoppingCart object increases. Xcode gives us four options to create a ShoppingCart object.

We can pass no values to the initializer. This is possible because each property has a default value.

let shoppingCart = ShoppingCart()

We can pass a value for the totalPrice property or a value for the numberOfItems property.

let shoppingCart2 = ShoppingCart(totalPrice: 10.0)
let shoppingCart3 = ShoppingCart(numberOfItems: 10)

We can also pass values for both properties.

let shoppingCart4 = ShoppingCart(totalPrice: 10.0, numberOfItems: 10)

How does this work? The memberwise initializer the compiler generates looks something like this. The compiler uses the default value of each property as the default value of the corresponding parameter of the memberwise initializer. There is no magic involved.

init(totalPrice: Double = 0, numberOfItems: Int = 0) {
    self.totalPrice = totalPrice
    self.numberOfItems = numberOfItems
}

When Is a Memberwise Initializer Not Available?

It is important to know that the compiler only generates a memberwise initializer for a struct if the type declaration doesn't define a custom initializer. Let's revisit the Book struct. We update the example by adding a custom initializer to the Book declaration.

import Foundation

struct Book {

    let title: String
    let author: String

    init(data: (String, String)) {
        title = data.0
        author = data.1
    }

}

Notice that Xcode's list of suggestions no longer includes the memberwise initializer. The only option we have to create a Book struct is the custom initializer we defined.

Defining a Custom Initializer for a Struct

A Workaround for a Missing Memberwise Initializer

It can happen that you define a custom initializer, but you also want the convenience of a memberwise initializer. This is surprisingly simple and you don't need to implement the memberwise initializer yourself. The solution is to define the custom initializer in an extension for the struct. Take a look at the updated example.

import Foundation

struct Book {

    let title: String
    let author: String

}

extension Book {

    init(data: (String, String)) {
        title = data.0
        author = data.1
    }

}

This gives us the best of both worlds.

Defining a Custom Initializer In an Extension

How to Create a Memberwise Initializer for Classes?

Even though the compiler only generates memberwise initializers for structs, it is possible to create one for classes. This is a little known feature of Xcode. Take a look at this example.

import Foundation

class Book {

    let title: String
    let author: String

}

I have converted the Book struct to a class. Because the compiler doesn't generate a memberwise initializer for classes, it throws an error. The error tells us that the Book class has no initializers. That is correct, but we can fix this with a few clicks.

Class Has No Initializers

Note that this solution only works in a project, not in a playground. This is a limitation of Xcode. Right-click the Book class to bring up the contextual menu. Choose Refactor > Generate Memberwise Initializer.

Generating a Memberwise Initializer for a Class

This is the result.

import Foundation

class Book {
    internal init(title: String, author: String) {
        self.title = title
        self.author = author
    }


    let title: String
    let author: String

}
Download Your Free Copy of
The Missing Manual
for Swift Development

The Guide I Wish I Had When I Started Out

Join 20,000+ Developers Learning About Swift Development

Download Your Free Copy