Standard: Swift Coding Standards
Baseline rules for all Swift code. Enforced by .swiftlint.yml where possible. These are law — generated code must conform.
Naming
- Types
UpperCamelCase; methods, properties, caseslowerCamelCase. - Booleans read as assertions:
isEnabled,hasLoaded,canSubmit. - Methods are verb phrases (
fetchAccounts()); avoidgetprefixes for accessors. - Avoid abbreviations except well-known ones (
id,url,min). No Hungarian notation. - Protocols describe capability (
-able/-ing) or role (AccountRepository).
swift
// ✅ // ❌
struct AccountSummary {} struct acct_summary {}
func loadTransactions() async {} func getTxns() {}
var isAuthenticated: Bool var auth: BoolTypes & Immutability
- Prefer value types (
struct/enum); useclass/actorwhen reference semantics or isolation is required. - Prefer
letovervar; minimize mutable state. - Use
enumfor finite states instead of loose booleans/strings. - Mark classes
finalunless designed for inheritance.
Optionals & Safety
- No force-unwrap (
!), force-try (try!), or force-cast (as!) on data that can be absent or untrusted. Useguard let/if let/??. - Use
guardfor early exit; keep the happy path unindented.
swift
// ✅
guard let user = session.user else { return }
// ❌
let user = session.user!Error Handling
- Use typed
Errorenums per domain; map errors at layer boundaries. - Never silently swallow errors with
try?unless the absence is genuinely fine (comment why). - No empty
catch {}blocks.
Concurrency
- Use Swift Concurrency (
async/await,Task, actors); avoidDispatchQueuefor new code. - UI types are
@MainActor. Protect shared mutable state with actors. - Always honor cancellation; cancel tasks in
deinit/teardown.
Functions & Files
- Functions do one thing; respect SwiftLint
function_body_length/cyclomatic_complexity. - One primary type per file (plus tightly-coupled helpers). Respect
file_length. - Order within a type: stored properties → init → public → private; group with
// MARK:.
Logging
- Use
os.Loggerwith privacy redaction; never log secrets/PII. - No
print()in committed code.
swift
import os
let log = Logger(subsystem: "com.app.networking", category: "http")
log.debug("Request \(endpoint.path, privacy: .public) user=\(userID, privacy: .private)")Documentation
- Document public APIs and non-obvious logic with
///doc comments. - Comments explain why, not what the code already says.
Dependencies
- Prefer Swift Package Manager; pin versions. Justify each third-party dependency.
- Wrap third-party SDKs behind your own protocol to limit blast radius.