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:

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:

As always, consistency and readability still win.