{"slug": "memberwise-initializer-in-swift-explained-with-code-examples", "title": "Memberwise Initializer in Swift explained with Code Examples", "summary": "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.", "body_md": "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.\n\nThis 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.\n\n[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.\n\n[Learn more](https://display.dev/?utm_source=swiftlee&utm_medium=newsletter&utm_campaign=swiftlee_sponsor).\n\nWhat is a memberwise initializer?\n\nA memberwise initializer is an initializer that Swift automatically generates for structs. It allows you to initialize each stored property directly:\n\n``` js\nstruct Article {\n    let title: String\n    let url: URL\n    var readCount: Int\n}\n\nlet article = Article(\n    title: \"Memberwise Initializers in Swift\",\n    url: URL(string: \"https://www.avanderlee.com\")!,\n    readCount: 0\n)\n```\n\nYou did not have to write this initializer yourself:\n\n```\ninit(title: String, url: URL, readCount: Int) {\n    self.title = title\n    self.url = url\n    self.readCount = readCount\n}\n```\n\nThe 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.\n\nDefault property values\n\nMemberwise 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:\n\n``` js\nstruct Article {\n    let title: String\n    let url: URL\n    var readCount: Int = 0\n}\n\nlet article = Article(\n    title: \"Memberwise Initializers in Swift\",\n    url: URL(string: \"https://www.avanderlee.com\")!\n)\n```\n\nIn this case, Swift still generates a parameter for `readCount`\n\n, but it gets a default value:\n\n```\n// Generated automatically:\ninit(title: String, url: URL, readCount: Int = 0)\n```\n\nThis 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.\n\nFREE 5-Day Email Course: The Swift Concurrency Playbook\n\nA **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)\n\nPrivate properties before Swift 6.4\n\nBefore Swift 6.4, private stored properties with default values could make the generated memberwise initializer much less useful:\n\n``` js\nstruct Article {\n    let title: String\n    let url: URL\n    private var readCount: Int = 0\n}\n\n// You would expect this to work, but it does not before Swift 6.4:\nlet article = Article(\n    title: \"Memberwise Initializers in Swift\",\n    url: URL(string: \"https://www.avanderlee.com\")!\n)\n```\n\nYou might expect this to work. After all, `readCount`\n\nis private and already has a default value, so callers should not have to know about it.\n\nHowever, before Swift 6.4, the compiler still included `readCount`\n\nin the memberwise initializer:\n\n```\n// Before Swift 6.4, readCount is still included although private:\nprivate init(title: String, url: URL, readCount: Int = 0)\n```\n\nSince the initializer included a private property, the initializer itself became private. As a result, creating the `Article`\n\noutside the struct would fail:\n\nThis often forced you to write a manual initializer just to hide a private implementation detail:\n\n``` js\nstruct Article {\n    let title: String\n    let url: URL\n    private var readCount: Int = 0\n\n    init(title: String, url: URL) {\n        self.title = title\n        self.url = url\n    }\n}\n```\n\nThe manual initializer works, but it removes part of the convenience that made the struct nice to use in the first place.\n\nPrivate properties in Swift 6.4\n\nSwift 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.\n\nIn practice, the earlier example becomes valid:\n\n``` js\nstruct Article {\n    let title: String\n    let url: URL\n    private var readCount: Int = 0\n}\n\nlet article = Article(\n    title: \"Memberwise Initializers in Swift\",\n    url: URL(string: \"https://www.avanderlee.com\")!\n)\n```\n\nSwift now generates the initializer you probably expected:\n\n```\n// Starting in Swift 6.4, readCount is no longer needed:\ninit(title: String, url: URL)\n```\n\nThe private `readCount`\n\nproperty still exists and still starts at `0`\n\n, but it no longer forces the memberwise initializer to become private. This is a small language improvement that removes a common source of boilerplate.\n\nI 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.\n\nWhich properties are excluded?\n\nSwift 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.\n\nAn initial value can be explicit:\n\n``` js\nstruct Article {\n    let title: String\n    private var readCount = 0\n}\n```\n\nIt can also be a default-initialized value, like an optional that starts as `nil`\n\n:\n\n``` js\nstruct Article {\n    let title: String\n    private var cachedSummary: String?\n}\n```\n\nIn Swift 6.4, both `readCount`\n\nand `cachedSummary`\n\ncan be excluded from the memberwise initializer when there are more accessible properties like `title`\n\n.\n\nHowever, a private property without an initial value still has to be initialized somehow:\n\n``` js\nstruct Article {\n    let title: String\n    private let identifier: UUID\n}\n```\n\nIn this case, Swift still includes `identifier`\n\nin the memberwise initializer. Since `identifier`\n\nis private, the initializer remains limited by that private access level:\n\n```\n// Still private, since `identifier` has no default value:\nprivate init(title: String, identifier: UUID)\n```\n\nThis makes sense. Swift cannot create an `Article`\n\nwithout knowing the `identifier`\n\n, so you still need to write a custom initializer if you want to hide that property from callers:\n\n``` js\nstruct Article {\n    let title: String\n    private let identifier: UUID\n\n    init(title: String) {\n        self.title = title\n        self.identifier = UUID()\n    }\n}\n```\n\nPublic structs still need explicit initializers\n\nThere is one important detail to remember: memberwise initializers are only synthesized up to `internal`\n\naccess. Even if your struct is `public`\n\n, Swift will not generate a public memberwise initializer for you.\n\nFor example:\n\n``` js\npublic struct Article {\n    public let title: String\n    public let url: URL\n}\n```\n\nSwift can synthesize an internal memberwise initializer for use inside the module, but clients of your module still cannot create `Article`\n\nunless you define a public initializer:\n\n``` js\npublic struct Article {\n    public let title: String\n    public let url: URL\n\n    public init(title: String, url: URL) {\n        self.title = title\n        self.url = url\n    }\n}\n```\n\nThis 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.\n\nSource compatibility\n\nSwift 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.\n\nFor example, Swift can synthesize both forms internally:\n\n``` js\nstruct Article {\n    let title: String\n    private var readCount: Int = 0\n\n    func resettingReadCount() -> Article {\n        Article(title: title, readCount: 0)\n    }\n}\n```\n\nA 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:\n\n``` js\nstruct Article {\n    let title: String\n    private var readCount: Int = 0\n\n    private init(title: String, readCount: Int) {\n        self.title = title\n        self.readCount = readCount\n    }\n}\n```\n\nThis makes your intent clear and avoids depending on a compatibility path that might go away later.\n\nWhy this change matters\n\nThis 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.\n\nIt 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.\n\nYou 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.\n\n[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.\n\n[Learn more](https://display.dev/?utm_source=swiftlee&utm_medium=newsletter&utm_campaign=swiftlee_sponsor).\n\nConclusion\n\nMemberwise 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.\n\nIf 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.\n\nIf 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.\n\nThanks!", "url": "https://wpnews.pro/news/memberwise-initializer-in-swift-explained-with-code-examples", "canonical_source": "https://www.avanderlee.com/swift/memberwise-initializers/", "published_at": "2026-06-29 13:40:35+00:00", "updated_at": "2026-07-22 07:34:39.478705+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Swift", "Swift 6.4", "SE-0242"], "alternates": {"html": "https://wpnews.pro/news/memberwise-initializer-in-swift-explained-with-code-examples", "markdown": "https://wpnews.pro/news/memberwise-initializer-in-swift-explained-with-code-examples.md", "text": "https://wpnews.pro/news/memberwise-initializer-in-swift-explained-with-code-examples.txt", "jsonld": "https://wpnews.pro/news/memberwise-initializer-in-swift-explained-with-code-examples.jsonld"}}