Skip to content

Conversation

@calda
Copy link
Member

@calda calda commented Dec 5, 2025

Summary

This PR updates the redundant memberwise init rule to also apply to structs with private properties. For internal SwiftUI views, prefer defining internal properties rather than private properties so the synthesized memberwise initializer can be used.

Autocorrect is implemented in the new --prefer-synthesized-init-for-internal-structs option added in nicklockwood/SwiftFormat#2291.

/// WRONG
struct PlanetView: View {

  // MARK: Lifecycle

  init(planet: Planet, star: Star) {
    self.planet = planet
    self.star = star
  }

  // MARK: Internal

  var body: some View {
    ...
  }

  // MARK: Private

  private let planet: Planet
  private let star: Star

}
/// RIGHT
struct PlanetView: View {
  let planet: Planet
  let star: Star

  var body: some View {
    ...
  }
}

Reasoning

This reduces boilerplate and makes it easier to add additional properties in the future.

This doesn't apply to SwiftUI dynamic properties, which should always be left private.

@calda calda changed the title Update redundant memberwise init rule to apply to structs with private properties Internal SwiftUI views should use synthesized memberwise initializer Dec 8, 2025
@calda calda force-pushed the cal--internal-struct-inits branch 3 times, most recently from 4f3a2d5 to 7935b44 Compare December 10, 2025 22:46
@calda calda force-pushed the cal--internal-struct-inits branch from 7935b44 to e1779e7 Compare December 10, 2025 22:46

</details>

- <a id='omit-internal-keyword'></a>(<a href='#omit-internal-keyword'>link</a>) **Omit the `internal` keyword** when defining types, properties, or functions with an internal access control level.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reorganized the access control rules to all be next to eachother


</details>

- <a id='omit-redundant-public'></a>(<a href='#omit-redundant-public'>link</a>) **Avoid using `public` access control in `internal` types.** In this case the `public` modifier is redundant and has no effect.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merged this rule into the "Access control should be at the strictest level possible" rule -- the wording of that rule already covered this behavior

**[⬆ back to top](#table-of-contents)**

## Objective-C Interoperability
## SwiftUI
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New top-level SwiftUI section!


**[⬆ back to top](#table-of-contents)**

## Objective-C Interoperability
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this below the "Testing" and "SwiftUI" sections. Realistically we may just want to remove it, but can do that separatety.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad we moved this further down 👍

@calda calda enabled auto-merge (squash) December 10, 2025 22:49
@calda calda merged commit 33e066c into master Dec 10, 2025
6 checks passed
@calda calda deleted the cal--internal-struct-inits branch December 10, 2025 22:50
Copy link
Contributor

@bachand bachand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @calda . LGTM!

1. [Patterns](#patterns)
1. [File Organization](#file-organization)
1. [Objective-C Interoperability](#objective-c-interoperability)
1. [SwiftUI](#swiftui)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

#### Why?

Removing redundant memberwise initializers reduces boilerplate and makes the code more concise. The compiler-synthesized initializers are equivalent to the explicit ones, so there's no functional difference.
Removing redundant memberwise initializers reduces boilerplate and makes it easier to add more properties in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

<details>

[![SwiftFormat: redundantFileprivate](https://img.shields.io/badge/SwiftFormat-redundantFileprivate-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#redundantFileprivate)
[![SwiftFormat: redundantFileprivate](https://img.shields.io/badge/SwiftFormat-redundantFileprivate-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#redundantFileprivate) [![SwiftFormat: redundantPublic](https://img.shields.io/badge/SwiftFormat-redundantPublic-7B0051.svg)](https://github.com/nicklockwood/SwiftFormat/blob/main/Rules.md#redundantPublic)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
```

However, you can use `internal` access control instead of `private` access control to enable the use of the [compiler-synthesized memberwise initializer](#omit-redundant-memberwise-init).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
```

This doesn't apply to SwiftUI dynamic properties, which should always be left private.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


**[⬆ back to top](#table-of-contents)**

## Objective-C Interoperability
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad we moved this further down 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants