Apple code style
SwiftFormat, SwiftLint, RuboCop, and Yamllint in the Apple project, and the coding conventions reviewers look for.
The Apple project formats and lints its code automatically, so reviews can focus on behavior and edge cases instead of style.
| Tool | Checks | Configured in |
|---|---|---|
| SwiftFormat | Swift formatting | .swiftformat |
| SwiftLint | Swift rules SwiftFormat doesn't cover, plus custom rules | .swiftlint.yml |
| RuboCop | The Ruby code of Fastlane | .rubocop.yml |
| Yamllint | Workflows and other YAML | .yamllint.yml |
# Report problems, change nothing
bundle exec fastlane lint
# Fix what can be fixed automatically
bundle exec fastlane autocorrectRun autocorrect before every commit. Or let git do it for you:
bundle exec fastlane install_git_hooksInside Xcode, the linters only show warnings and don't change your code. CI also runs Yamllint, which is not part of the lint lane.
- Formatting: lines up to 120 characters, arguments and collections wrapped before the first element,
selfonly in initializers,guardandelseon the same line, and no file header comments. - SwiftLint uses an allowlist of rules, not every default rule. Among them: no
force_castorforce_try, and low cyclomatic complexity. - Custom SwiftLint rules: never assign to
Currentoutside tests, and useSFSafeSymbolsinstead of raw SF Symbol names.
// Wrong
Image(systemName: "house")
// Right
Image(systemSymbol: .house)Be careful with // swiftlint:disable. CI looks for new ones in every pull request, and comments when it finds one (on pull requests from a branch in the repository itself), so a maintainer can check that it is really needed. Every suppression needs a good reason.
- One type per file, named after the type, and a
#Previewfor every SwiftUI view. See rules for every change. - Log with
Current.Log, neverprintorNSLog. - Small, well-named types and functions that are easy to test on their own.
- Shared code goes in shared modules, instead of being copied between targets. Don't put assumptions about one target into shared or extension code.
- User facing text goes in
en.lproj/Localizable.strings. SwiftGen generates theL10naccessors you use in code, and translations come from Lokalise.
Some files are generated by tools or workflows, like the L10n accessors and the icon and color sets. Generated files usually say so in a comment at the top. Don't edit them by hand: change the source and run the tool. When you touch Ruby or workflow code, make sure its linters still pass.