Memberwise Initializer in Swift explained with Code Examples Swift 6.4 improves the default behavior of memberwise initializers for structs with private stored properties, making them more useful by no longer including private properties with default values in the generated initializer. The compiler automatically generates memberwise initializers for structs, allowing developers to create instances without manually writing an initializer, a feature that keeps simple model types short and readable. Memberwise initializers in Swift allow you to create struct instances without manually writing an initializer. The compiler examines the stored properties of your struct and automatically generates an initializer that accepts values for them. This feature is one of the reasons why structs are so lightweight to use in Swift. However, there are a few details around access control and private properties that can surprise you. Swift 6.4 improves the default behavior, making memberwise initializers more useful when your struct contains private implementation details. Share your AI agent’s work with your team https://display.dev/?utm source=swiftlee&utm medium=newsletter&utm campaign=swiftlee sponsor Your agent generates a report, dashboard, or prototype as HTML or Markdown. display.dev turns it into a secure URL your team can open with their existing work login, comment on inline, and send back to any agent through MCP. Works with Cursor, Codex, Claude Code, and more. No viewer accounts, no seat management, no vendor lock-in. Learn more https://display.dev/?utm source=swiftlee&utm medium=newsletter&utm campaign=swiftlee sponsor . What is a memberwise initializer? A memberwise initializer is an initializer that Swift automatically generates for structs. It allows you to initialize each stored property directly: js struct Article { let title: String let url: URL var readCount: Int } let article = Article title: "Memberwise Initializers in Swift", url: URL string: "https://www.avanderlee.com" , readCount: 0 You did not have to write this initializer yourself: init title: String, url: URL, readCount: Int { self.title = title self.url = url self.readCount = readCount } The compiler generates it for you. This keeps simple model types short and readable, which is one of the reasons I often start with a struct by default. Default property values Memberwise initializers also support default property values. If a stored property has a default value, Swift uses that value as the default argument in the generated initializer: js struct Article { let title: String let url: URL var readCount: Int = 0 } let article = Article title: "Memberwise Initializers in Swift", url: URL string: "https://www.avanderlee.com" In this case, Swift still generates a parameter for readCount , but it gets a default value: // Generated automatically: init title: String, url: URL, readCount: Int = 0 This behavior was improved in Swift 5.1 through SE-0242: Synthesize default values for the memberwise initializer https://github.com/swiftlang/swift-evolution/blob/main/proposals/0242-default-values-memberwise.md . I already touched on this briefly in my article about structs vs classes in Swift https://www.avanderlee.com/swift/struct-class-differences/ , but Swift 6.4 adds another useful improvement. FREE 5-Day Email Course: The Swift Concurrency Playbook A FREE 5-day email course revealing the 5 biggest mistakes iOS developers make with with async/await that lead to App Store rejections And migration projects taking months instead of days even if you've been writing Swift for years Private properties before Swift 6.4 Before Swift 6.4, private stored properties with default values could make the generated memberwise initializer much less useful: js struct Article { let title: String let url: URL private var readCount: Int = 0 } // You would expect this to work, but it does not before Swift 6.4: let article = Article title: "Memberwise Initializers in Swift", url: URL string: "https://www.avanderlee.com" You might expect this to work. After all, readCount is private and already has a default value, so callers should not have to know about it. However, before Swift 6.4, the compiler still included readCount in the memberwise initializer: // Before Swift 6.4, readCount is still included although private: private init title: String, url: URL, readCount: Int = 0 Since the initializer included a private property, the initializer itself became private. As a result, creating the Article outside the struct would fail: This often forced you to write a manual initializer just to hide a private implementation detail: js struct Article { let title: String let url: URL private var readCount: Int = 0 init title: String, url: URL { self.title = title self.url = url } } The manual initializer works, but it removes part of the convenience that made the struct nice to use in the first place. Private properties in Swift 6.4 Swift 6.4 implements SE-0502: Exclude private initialized properties from memberwise initializer https://github.com/swiftlang/swift-evolution/blob/main/proposals/0502-exclude-private-from-memberwise-init.md . The generated memberwise initializer now excludes less accessible properties that already have an initial value. In practice, the earlier example becomes valid: js struct Article { let title: String let url: URL private var readCount: Int = 0 } let article = Article title: "Memberwise Initializers in Swift", url: URL string: "https://www.avanderlee.com" Swift now generates the initializer you probably expected: // Starting in Swift 6.4, readCount is no longer needed: init title: String, url: URL The private readCount property still exists and still starts at 0 , but it no longer forces the memberwise initializer to become private. This is a small language improvement that removes a common source of boilerplate. I like this change because it better matches how I think about private stored properties. If a property is private and already initialized, it usually feels like an implementation detail. Callers should not have to pass it into the initializer. Which properties are excluded? Swift 6.4 does not simply remove every private property from memberwise initializers. The rule is more precise: a property is excluded when it is less accessible than the generated initializer and already has an initial value. An initial value can be explicit: js struct Article { let title: String private var readCount = 0 } It can also be a default-initialized value, like an optional that starts as nil : js struct Article { let title: String private var cachedSummary: String? } In Swift 6.4, both readCount and cachedSummary can be excluded from the memberwise initializer when there are more accessible properties like title . However, a private property without an initial value still has to be initialized somehow: js struct Article { let title: String private let identifier: UUID } In this case, Swift still includes identifier in the memberwise initializer. Since identifier is private, the initializer remains limited by that private access level: // Still private, since identifier has no default value: private init title: String, identifier: UUID This makes sense. Swift cannot create an Article without knowing the identifier , so you still need to write a custom initializer if you want to hide that property from callers: js struct Article { let title: String private let identifier: UUID init title: String { self.title = title self.identifier = UUID } } Public structs still need explicit initializers There is one important detail to remember: memberwise initializers are only synthesized up to internal access. Even if your struct is public , Swift will not generate a public memberwise initializer for you. For example: js public struct Article { public let title: String public let url: URL } Swift can synthesize an internal memberwise initializer for use inside the module, but clients of your module still cannot create Article unless you define a public initializer: js public struct Article { public let title: String public let url: URL public init title: String, url: URL { self.title = title self.url = url } } This is not new in Swift 6.4, but it is easy to forget when working with Swift packages. If you are exposing models from a package, you still need to decide which initializers are part of your public API. Source compatibility Swift 6.4 includes a compatibility overload for the old memberwise initializer shape. This means existing code that initializes private properties through the synthesized initializer can continue to work for now. For example, Swift can synthesize both forms internally: js struct Article { let title: String private var readCount: Int = 0 func resettingReadCount - Article { Article title: title, readCount: 0 } } A future language mode could remove this compatibility overload. If your code relies on initializing private properties through the generated memberwise initializer, I would make that initializer explicit instead: js struct Article { let title: String private var readCount: Int = 0 private init title: String, readCount: Int { self.title = title self.readCount = readCount } } This makes your intent clear and avoids depending on a compatibility path that might go away later. Why this change matters This change makes memberwise initializers better align with access control. A private property with a default value is usually an implementation detail, so it should not reduce the usefulness of the initializer that callers actually use. It also helps macro authors. Attached macros often need to add private backing storage, similar to property wrappers. Before Swift 6.4, that private storage could accidentally make the generated initializer private, forcing you to write boilerplate. You do not need to know all macro details to benefit from the change. The simple takeaway is this: you can add private initialized storage to a struct without losing the convenient memberwise initializer for the properties that matter to callers. Share your AI agent’s work with your team https://display.dev/?utm source=swiftlee&utm medium=newsletter&utm campaign=swiftlee sponsor Your agent generates a report, dashboard, or prototype as HTML or Markdown. display.dev turns it into a secure URL your team can open with their existing work login, comment on inline, and send back to any agent through MCP. Works with Cursor, Codex, Claude Code, and more. No viewer accounts, no seat management, no vendor lock-in. Learn more https://display.dev/?utm source=swiftlee&utm medium=newsletter&utm campaign=swiftlee sponsor . Conclusion Memberwise initializers in Swift remove boilerplate by letting the compiler generate struct initializers for stored properties. Default values make them even more convenient, and Swift 6.4 improves the behavior further by excluding private initialized properties when they should behave like implementation details. If you are using private stored properties with default values, you might be able to remove manual initializers after adopting Swift 6.4. Just remember that private properties without default values still need initialization, and public structs still require explicit public initializers. If you want to improve your Swift knowledge even more, check out the Swift category page https://www.avanderlee.com/swift/ . Feel free to contact me or tweet me on Twitter https://twitter.com/twannl if you have any additional tips or feedback. Thanks