Skip to main content

Code Style

.swiftlint.yml and .swiftformat are the source of truth. When in doubt, check those files.

Core Rules

  • No comments. Code must be self-explanatory through naming and structure. Do not add comments that describe what code does, reference tickets, or explain callers.
  • Early returns. Use guard and early return instead of nested if/else blocks. Flatten control flow.

Tools

There is no SwiftLint build phase in the Xcode project. Lint runs manually and in CI.

Formatting

Trailing commas are omitted by convention. Both tools have their trailing-comma rules disabled, so nothing enforces it.

Naming

Access Control

Always explicit. Prefer the most restrictive level that works.

Imports

One alphabetical block, no blank lines between imports, one blank line after the last import. SwiftFormat enforces this (--importgrouping alpha, blankLinesBetweenImports, blankLineAfterImports).

Safety

No force unwrapping (!) or force casting (as!). Use guard let, if let, as?.

Logging

OSLog only. Never print().

Localization

  • String(localized:) for user-facing strings in computed properties, AppKit code, alerts, error descriptions
  • SwiftUI view literals (Text("Save"), Button("Cancel")) auto-localize
  • Do not localize technical terms: font names, database types, SQL keywords, encoding names
  • Never use String(localized:) with string interpolation. Use String(format: String(localized: "Preview %@"), name) instead.

SwiftUI Patterns

  • @State for local view state
  • @Observable for viewmodels (Swift 5.9+)
  • Property wrapper order: Environment, State, Binding, regular properties
  • Extract large views into subviews

Limits

When approaching these limits, extract into extension files:
MainContentCoordinator.swift
Extensions
MainContentCoordinator+RowOperations.swift
MainContentCoordinator+Pagination.swift
MainContentCoordinator+Filtering.swift
Group by domain logic, not arbitrary line counts.