Code Organization and Style Tools
Prerequisites: Swift Package Manager, Access control
As a project grows, a consistent structure and automatic style checks keep it readable.
Organizing files
- One main type per file, named after it:
Cart.swiftholdsstruct Cart. - Group by feature, not by kind.
Checkout/,Profile/, andSearch/folders — each with its own models, views, and logic — scale better than one giantModels/and one giantViews/folder. - Use extensions to divide a type into sections, typically one per
protocol conformance, marked with
// MARK: -comments that Xcode shows in its jump bar:
struct Invoice {
let lines: [Double]
}
// MARK: - Totals
extension Invoice {
var subtotal: Double { lines.reduce(0, +) }
}
// MARK: - CustomStringConvertible
extension Invoice: CustomStringConvertible {
var description: String { "Invoice(\(lines.count) lines)" }
}
- Split into modules as the project grows: Swift package targets for networking, models, and features let each part build and be tested on its own, and access control between modules enforces boundaries.
Formatting: swift-format
swift-format (from the Swift project, included with Swift 6 toolchains) formats code consistently:
swift format --in-place --recursive Sources Tests
Xcode can also re-indent a selection with Ctrl + I.
Linting: SwiftLint
SwiftLint checks for style issues and common mistakes — force unwrapping, overly long functions, unused code:
Sources/Shop/Cart.swift:14:22: warning: Force Unwrapping Violation: Force unwrapping should be avoided (force_unwrapping)
Rules are configured in a .swiftlint.yml file. Running the formatter
and linter in your editor and in CI means style never has to be argued
about in code review.
Common mistakes
- Views with hundreds of lines of mixed UI and business logic. Move logic into separate types that can be tested.
- Disabling every lint rule that complains. Read why the rule exists first — many point to real bugs.