Skip to content
AgileLogics
5 min read

Initializers

Prerequisites: Methods and mutating

An initializer (init) sets up a new instance. Swift guarantees that every property has a value before an instance can be used.

Custom initializers

struct Temperature {
    var celsius: Double

    init(celsius: Double) {
        self.celsius = celsius
    }

    init(fahrenheit: Double) {
        celsius = (fahrenheit - 32) * 5 / 9
    }
}

let a = Temperature(celsius: 25)
let b = Temperature(fahrenheit: 212)
print(a.celsius, b.celsius)
25.0 100.0

Different argument labels let a type offer several clear ways to be created. Note that writing your own init inside the struct removes the automatic memberwise initializer. To keep both, put custom initializers in an extension (a later lesson).

Failable initializers

init? can return nil when the input isn't valid:

struct Email {
    let address: String

    init?(_ address: String) {
        guard address.contains("@"), !address.hasPrefix("@") else {
            return nil
        }
        self.address = address
    }
}

let good = Email("ada@example.com")
let bad = Email("not-an-email")
print(good?.address ?? "invalid")
print(bad?.address ?? "invalid")
ada@example.com
invalid

Email(...) returns an Email?. Validating in the initializer means an Email value, once it exists, is always valid — the rest of your code never needs to check again. Int("42") is a failable initializer you've used from the start.

Common mistakes

  • Leaving a property without a value in init: return from initializer without initializing all stored properties.
  • Calling a method on self before every property is set.