Swift How to Initialize a Struct (No ‘init’ with Structs?)

To initialize a struct in Swift, you do not need to write the init method. This is because, by default, there is a memberwise initializer that does the job behind the scenes.

For instance:

struct Fruit {
    let name: String?
}

As you can see, this structure does not implement an init method. But you can create a Fruit object like this:

let banana = Fruit(name: "Banana")
print(banana.name!)

Output:

Banana

This is because Swift auto-generates an initializer for a struct.

In this guide, you learn how to use the auto-generated memberwise initializer in Swift structures.

Memberwise Initializer in Swift Structs

In Swift, all structs come with a default initializer. This is called the memberwise initializer.

A memberwise initializer assigns each property in the structure to self. This means you do not need to write an implementation for an initializer in your structure.

For instance:

struct Fruit {
    let name: String?
    let color: String?
    let weight: Double?
}

Now let’s instantiate a Fruit object:

let banana = Fruit(name: "Banana", color: "Yellow", weight: 0.3)

print(banana.name!)
print(banana.color!)
print(banana.weight!)

Output:

Banana
Yellow
0.3

This works because you instantiate an object, and the memberwise initializer runs behind the scenes. It assigns each argument value to the related property in the structure.

When using a memberwise initializer, you need to provide values (or nils) to all the properties of the structure. Otherwise, the initialization fails.

For example, let’s try to create a Fruit object by only specifying a name for it:

let banana = Fruit(name: "Banana")
print(banana.name!)

This results in an error:

main.swift:11:34: error: missing argument for parameter 'color' in call
let banana = Fruit(name: "Banana")

As you can see, Swift expects you to provide values for all the properties inside the Fruit structure.

If you do not want to give values to the other properties, you can pass nil as the undefined values:

For instance, let’s create Fruit by only specifying a name:

let banana = Fruit(name: "Banana", color: nil, weight: nil)
print(banana.name!)

Output:

Banana

Another way to overcome the issue is by actually writing a custom initializer to the structure.

For instance, let’s write an initializer for the Fruit structure that defaults the properties to nil:

struct Fruit {
    let name: String?
    let color: String?
    let weight: Double?

    init(name: String? = nil, color: String? = nil, weight: Double? = nil) {
        self.name = name
        self.color = color
        self.weight = weight
    }
}

Now you can create Fruit objects without having to provide each property a value.

For example, let’s create Fruit objects with a varying number of arguments:

let banana = Fruit(name: "Banana")
let apple = Fruit(name: "Apple", color: "Red")
let orange = Fruit(name: "Orange", color: "Orange", weight: 0.3)

Now you understand what is a memberwise initializer in Swift.

Next, let’s take a look at what happens to the memberwise initializer when you write a custom initializer to the structure.

Add a Custom Initializer without Losing Memberwise Initializer

When you write a custom initializer for a struct in Swift, the memberwise initializer goes away.

For example, let’s create a Fruit structure with a custom initializer:

struct Fruit {
    let name: String?
    let color: String?
    let weight: Double?

    init(_ csv: String) {
        let parts = csv.components(separatedBy: ",")
        self.name = parts[0]
        self.color = parts[1]
        self.weight = Double(parts[2])
    }
}

Now you can only initialize a Fruit object by giving it the arguments as a comma-separated string.

For example:

let banana = Fruit("Banana,yellow,0.3")

print(banana.name!)
print(banana.color!)
print(banana.weight!)

Output:

Banana
yellow
0.3

It is not possible to use the default initializer like this:

let orange = Fruit(name: "Orange", color: "Orange", weight: 0.3)

This results in an error:

main.swift:23:43: error: extra argument 'color' in call
let orange = Fruit(name: "Orange", color: "Orange", weight: 0.3)

This error is thrown because as we have a custom initializer, the default initializer is gone for good.

However, there is a way to keep the default initializer in place even after writing a custom initializer.

To do this, write the custom initializer in an extension.

For example:

struct Fruit {
    let name: String?
    let color: String?
    let weight: Double?
}

extension Fruit {
    init(_ csv: String) {
        let parts = csv.components(separatedBy: ",")
        self.name = parts[0]
        self.color = parts[1]
        self.weight = Double(parts[2])
    }
}

Now the Fruit structure has two initializers:

  • The default memberwise initializer
  • The custom initializer

This means it is possible to use both to create new Fruit objects.

For example:

let banana = Fruit("Banana,yellow,0.3")
let orange = Fruit(name: "Orange", color: "Orange", weight: 0.3)

Now you understand how initializers work with structures in Swift.

Memberwise Initializer in a Class?

In Swift, a class does not have a default initializer.

For example:

class Fruit {
    let name: String?
    let color: String?
    let weight: Double?
}

let orange = Fruit(name: "Orange", color: "Orange", weight: 0.3)

This results in the following error:

main.swift:11:14: error: 'Fruit' cannot be constructed because it has no accessible initializers
let orange = Fruit(name: "Orange", color: "Orange", weight: 0.3)

The error message is pretty clear. The Fruit class does not have an initializer that could be used to initialize a Fruit object.

Conclusion

Today you learned how to initialize a struct in Swift.

To recap, a structure comes with a default initializer called a memberwise initializer. This makes it possible to instantiate objects without implementing an init method to the structure.

When you write a custom initializer to a structure, the memberwise initializer is gone.

To write a custom initializer and keep the default one, write the custom initializer into an extension.

Thanks for reading. Happy coding!

Scroll to Top