Swift Coding Style Guide (Version 1.0.1)
For a compact summary, see the Swift Coding Style Cheat Sheet.
1. Scope
The layout rules in this guide originated in the C Coding Style Guide, but this document contains their Swift-specific form in full. Use this guide directly when writing Swift.
Swift syntax sometimes requires a different form, but it must preserve the same layout decision wherever possible.
2. General Rules
All normal project rules still apply.
Comments and identifiers stay in English.
Indentation uses tabs. A tab counts as 4 spaces.
Tabs are used strictly for indentation. For alignment, use spaces.
Source lines must not exceed 80 characters. The line break counts as a character, so the last visible source character may only occupy column 79.
Consistency with surrounding code wins when multiple forms are allowed by this guide.
3. Line Breaking
When a single expression must be broken, indent the continuation line. When it breaks again, do not indent again unless a sub-expression also breaks.
Break before mathematical operators (+, -, *, /, %) and logical or bitwise operators (&&, ||, &, |, ^, <<, >>).
Break after assignment operators (=).
For assignment expressions, prefer breaking after = when both are possible.
For example:
let value =
(getSomeFunctionOutput(input) + someOtherValue) * someFactor
Break before comparison operators (==, !=, <, >, <=, >=).
Break before the member-access operator (.).
Break directly after (, [, or { when that delimiter starts a broken expression.
When closing a broken expression, place closing ), ], and } on their own unindented lines.
When a broken control-flow head or function signature starts a block, place the final ) at the end of its final condition or parameter line and place { on the next line.
Examples:
let result = firstValue
+ secondValue
+ thirdValue
let result = firstValue + (
secondValue
+ thirdValue
)
let value = fetchValue(
source,
style
)
let value = fetchValue(
getSource(
source
).name
)
let value = object
.property
.nestedProperty
if firstValue == secondValue
&& thirdValue == fourthValue
{
}
4. Imports and File Layout
Prefer the same top-to-bottom file structure used in existing Swift files in this project.
Keep one import per line.
Typical order:
- file header comment
- imports
- type or extension declaration
MARK:sections- properties
- functions
- nested helper functions only when they are tightly local to one outer function
Example:
import Foundation
import AppKit
extension SessionStateProvider {
...
// ------------------------------------------------------------------------
// MARK: Important Section
...
}
5. Types, Extensions, and Modifiers
Type declarations follow the variable style, not the function style.
Keep access modifiers and type modifiers on the same line for types.
Use modifier order such as private static, never static private.
Put the opening { of a type or extension on the same line.
Prefer the same blank-line spacing between sections that neighboring Swift files use.
Examples:
private enum State {
case idle
case running
}
public final class ServiceController {
}
private extension SessionStateProvider {
}
6. Properties and Other Stored Values
Variables, constants, typealiases, and nested types use the same-line modifier style.
Keep private, public, internal, fileprivate, open, static, and similar modifiers on the same line as let, var, typealias, enum, struct, class, actor, and protocol.
Use private static, never static private.
Keep short computed properties on one line when they stay readable.
Break after = when a value expression must wrap.
Break before ?? when the nil-coalescing expression must wrap.
Examples:
private let defaultPort = 443
private static let emptyValue = ""
var servicePort: UInt16 { self.fetchServicePort() }
private let host =
component.host
?? fallbackHost
7. Functions and Initializers
Functions follow the line-breaking rules in this guide.
Put function-level modifiers on their own lines above the func, init, subscript, or deinit declaration.
If a function has multiple modifiers, keep each modifier on its own line and keep the normal modifier order, for example private before static.
Keep static on its own line for functions, even though it stays on the same line for variables.
Put the opening { of a function body on its own line.
There is no space between the function name and ( ) in calls.
Function declarations and definitions may be broken along their parameters.
If the signature fits well, keep the return type on the same line.
If needed, break before -> and indent the return type by one level.
Examples:
private
func reload( )
{
}
static
func dictionaryMatchesStoredSession( _ dict: [String: Any] )
-> Bool
{
}
private static
func makeValue( ) -> Int
{
}
func convert(
host: String,
port: UInt16,
path: String ) -> URL?
{
}
func convert(
host: String,
port: UInt16,
path: String )
-> URL?
{
}
8. Parameters, Generics, and Type Syntax
Apply this guide's spacing rules to Swift syntax instead of switching to unrelated Swift-community defaults.
Keep generic syntax compact and consistent with surrounding Swift code.
When generic parameter lists or constraints must wrap, break them like other comma-separated lists.
Prefer where clauses only when they improve readability over inline constraints.
Keep attributes such as @objc on their own lines above the declaration they modify.
Keep parameter labels and names attached to their types in normal Swift syntax.
Examples:
func makeMap( _ values: [String: Any] ) -> [String: URL]
private enum ResultBox<Value, Failure: Error> {
case value(Value)
case failure(Failure)
}
9. Control Flow
Control flow follows the line-breaking rules in this guide.
Put { on the same line as if, guard ... else, for, while, and switch only when the control-flow head also ends on that line.
If the control-flow head breaks, the opening { moves to its own line.
Prefer early returns and early exits.
One-line if forms are preferred when they remain simple and readable.
Multi-statement branches use braces normally.
Examples:
if condition { action() }
guard value != nil else { return }
if condition
{
action()
}
10. If and Guard Line Breaking
if and guard conditions should use the expression layout in this guide, not formatter-driven hanging indents.
Keep single-condition forms on one line when they fit.
When breaking a normal condition list, keep if or guard on the first line and align the following conditions one indentation level deeper.
When the expression becomes deeply nested or visually heavy, if or guard may stand alone on its own line, followed by the conditions below it.
Comma-separated condition lists break after commas.
The opening { follows the same rule as elsewhere: same line only when the control-flow head also ends there.
else may stay on the same line as the last condition if that remains clear.
else may also move to its own line when that avoids a large indentation drop or makes a long guard easier to scan.
Examples:
if cond,
otherCond,
finalCond
{
}
if
call(
param1, param2
),
call2(
param1, param2
)
{
}
guard cond else { return }
guard cond
else { return }
guard cond
else
{
return
}
guard
cond,
otherCond,
finalCond
else
{
return
}
11. Switch Statements
switch uses explicit indentation.
Indent case and default one level inside switch.
Indent the case body one further level inside the case.
Keep simple cases on one line when they fit.
When a case pattern does not fit on one line, break after case and list the alternatives one per line.
Put the trailing : on the final pattern line.
Examples:
switch state {
case .idle:
return
case
.waiting,
.running,
.stopping:
handleTransition()
default:
break
}
12. Calls, Collections, and Closing Delimiters
Use the line-breaking rules in section 3.
Break directly after (, [, or { when those delimiters start a broken expression.
Do not increase indentation again when breaking the same expression repeatedly unless a sub-expression is broken.
Place closing ), ], and } on their own unindented lines when they close a broken expression.
This is especially useful in nested calls inside if, guard, or assignment expressions.
Keep commas attached to the preceding element.
Examples:
let value = call(
arg1,
arg2,
arg3
)
if
firstCall(
arg1, arg2
),
secondCall(
arg1,
arg2
)
{
}
13. Return Statements and Expressions
Return statements favor clarity.
Return a simple single value directly when it fits.
If the returned expression is complex or spans multiple operators, wrap it in ( ).
Break before ?? when that produces the cleaner wrapped expression.
Add parentheses where they improve readability, even when Swift precedence would make them optional.
If a comparison result is part of a larger expression, enclose the comparison in parentheses unless the larger expression is already enclosed in parentheses.
If a ternary expression must break, break after ? and before : only when necessary. Enclose a ternary expression in parentheses when it is part of a complex statement.
Examples:
return value
return (
primaryValue
?? fallbackValue
)
let value = condition ?
valueIfTrue
: valueIfFalse
14. Preference Rule
When ordinary Swift style advice and this guide disagree, prefer this guide.
That applies especially to:
- tabs for indentation
- continuation indentation from section 3
- function modifiers on their own lines
- same-line modifiers for variables and types
private static, neverstatic private- indented
switchcases - one-line
ifandguardwhen they fit - broken
ifandguardlayouts that avoid large indentation jumps - explicit closing-delimiter placement in nested expressions
As always, consistency and readability still win.