When can a struct’s memberwise initializer be used?
In Swift, types defined as structs automatically get a default initializer synthesized by the compiler — a so-called “memberwise initializer”, as the compiler will generate it based on the given struct’s members (that is, its stored properties).
For example, if we’ve defined a User
struct that has a name
and a preferences
property, we can use its memberwise initialize to create instances simply by passing values for those two properties:
struct User {
var name: String
var preferences: Preferences
}
let user = User(name: "John", preferences: Preferences())
Computed properties, on the other hand, are completely ignored when the compiler synthesizes a memberwise initializer — so even if we add one, we can still keep using the above initializer just like before:
struct User {
var name: String
var preferences: Preferences
var icon: Icon { .user }
}
let user = User(name: "John", preferences: Preferences())
As of Swift 5.1, memberwise initializers also take default property values into account — meaning that if we give our preferences
property a default value, we’ll be able to create a User
instance by just passing a name
:
struct User {
var name: String
var preferences = Preferences()
}
let user = User(name: "John")
One cool thing is that we can keep using a type’s memberwise initializer even if that type has private properties — as long as those properties have a default value, like this:
struct User {
var name: String
private var preferences = Preferences()
}
let user = User(name: "John")
However, if a private property doesn’t have a default value, we’ll have to write that type’s initializer manually — in order to be able to inject a value for that property from the outside:
struct User {
var name: String
private var preferences: Preferences
init(name: String, preferences: Preferences = .init()) {
self.name = name
self.preferences = preferences
}
}
One thing to keep in mind, though, is that memberwise initializers will never have an access level higher than internal
, which means that we can only use them internally within the module in which their type is defined.
That might initially seem like a strange restriction, but it does have merits, as we should arguably always design explicit APIs for public consumption — without making them tied to the internal structure of our data.
So, to sum up, we can use a struct’s memberwise initializer when:
- All of its members are either visible, or have a default value.
- We are creating an instance within the same module that the struct is defined in.
All other cases require us to manually implement an initializer, at least for now.
Support Swift by Sundell by checking out this sponsor:

Bitrise: My favorite continuous integration service. Automatically build, test and distribute your app on every Pull Request — which lets you quickly get feedback on each change that you make. Start 2021 with solid continuous integration from Bitrise, using hundreds of ready-to-use steps.