Whitespace
Indentation
Before lines, use 4 spaces , not tabs (set this in your preferences). Allow the IDE to guide your indentation practices; if it automatically indents something, don’t change that, but adopt it.
Always indent inside curly-brace-blocks, with the sole exception of switch
case
s, which appear at the same indentation level as the switch
statement, itself.
When there are multiple parts of an if
, else
, guard
, or while
statement, chop them down and align as the IDE prefers. This makes it clear that you have one clear intent for each line.
Good
Bad
if ( ! foo && baz )
|| ( qux && baz ) {
// Content...
}
guard
let hoge = self . hoge ,
let norf = hoge . norf ,
norf . isInitialized
else {
assertionFailure ( "hoge and norf are required" )
return
}
if ( ! foo && baz ) || ( qux && baz ) {
// Content...
}
guard let hoge = self . hoge , let norf = hoge . norf , norf . isInitialized else {
assertionFailure ( "hoge and norf are required" )
return
}
switch parseError {
case nil :
return . success
case . undefinedKey :
continue
case . unexpectedToken :
return . failure
}
switch parseError {
case nil :
return . success
case . undefinedKey :
continue
case . unexpectedToken :
return . failure
}
Chopping-Down Functions
When a function has a long declaration with many parameters, it may be chopped-down at both the declaration and the call site. That is to say, hard-wrapped so that they align nicely. If you prefer to keep it all on one line, that is also OK.
Don’t chop-down Objective-C style (so that colons align).
Good
Bad
func foobar ( _ baz : Baz ,
for qux : Qux ,
hoge : Hoge ,
norfProvider : (() -> Norf )?) -> Foobar {
// Content...
}
func foobar ( _ baz : Baz , for qux : Qux , hoge : Hoge , norfProvider : (() -> Norf )?) -> Foobar {
// Content...
}
let x = foobar ( baz ,
for : Qux (),
hoge : baz . hoge ,
norfProvider : nil )
let x = foobar ( baz , for : Qux (), hoge : baz . hoge , norfProvider : nil )
func foobar ( _ baz : Baz , for qux : Qux ,
hoge : Hoge , norfProvider : (() -> Norf )?) -> Foobar {
// Content...
}
func foobar ( _ baz : Baz ,
for qux : Qux ,
hoge : Hoge ,
norfProvider : (() -> Norf )?
) -> Foobar {
// Content...
}
let x = foobar ( baz , for : Qux (),
hoge : baz . hoge , norfProvider : nil )
let x = foobar ( baz ,
for : Qux (),
hoge : baz . hoge ,
norfProvider : nil )
Inline Padding
The quick summary of the below table is:
Colons are X: Y
or X : Y
Put a space before opening curly braces
Put a space around the assignment “=
”
Don’t put spaces around parentheses and angle brackets unless some other rule dictates that you should
Keep parentheses as close to the tokens they group as possible
Place Number of spaces Good Bad
Around typing colon
Depending on preference
class Foo : Bar {
// Content...
}
struct Baz : Qux {
let hoge : Hoge
var norf : Norf
}
class Foo : Bar {
// Content...
}
struct Baz : Qux {
let hoge : Hoge
var norf : Norf
}
Generics’ angle brackets
Keep them flush with the type they modify and the types within them.
Rules dictating more spacing override this (do place a space after closing angle bracket and opening curly brace).
class Foo < Baz > {
// Content...
}
class Bar : Qux < Hoge , Norf > {
// Content...
}
class Foo < Baz > {
// Content...
}
class Bar : Qux < Hoge , Norf > {
// Content...
}
After type declaration
Between last declaration character and opening curly brace
struct Foo {
// Content...
}
protocol Bar : Baz {
// Content...
}
class Qux : Hoge < Norf > {
// Content...
}
struct Foo {
// Content...
}
protocol Bar : Baz {
// Content...
}
class Qux : Hoge < Norf > {
// Content...
}
Around assignment “=
”
Around operators
Consecutive assignments are allowed to have more spacing for pretty alignment.
Note that Swift will not allow things like x= y
or x =y
.
let foo = 5 + 7
var bazqux = false
let hoge = "norf"
let foo = 5 + 7
var bazqux = false
let hoge = "norf"
let foo = 5 + 7
var foobar = false
let hoge = "norf"
let foo = 5 + 7
var bazqux = false
let hoge = "norf"
Functions
0 between name and open parenthesis
0 between open parenthesis and first parameter label (or close parenthesis if no parameters)
0 before commas between parameters
1 after commas between parameters
0 between last parameter and close parenthesis
1 between close parenthesis and open brace
func foo ( bar baz : Qux , hoge : Norf ) {
// Content...
}
func foo2 () -> Bool {
return true
}
func foo ( bar baz : Qux , hoge : Norf ){
// Content...
}
func foo2 ( ) -> Bool {
return true
}
if
, else
, guard
, switch
, while
, and for
statements
1 around (but not within) necessary parentheses
1 before opening brace
Spaces emerge from other rules;
First write or imagine it without parentheses. Then, place parentheses as necessary to group elements.
guard foo else {
assertionFailure ( "need foo" )
return
}
if ( bar && baz ) || qux {
// Content...
}
guard ( foo ) else {
assertionFailure ( "need foo" )
return
}
if ( bar && baz ) || qux {
// Content...
}
Blank Lines
When in doubt, more blank lines are okay. It’s better for readability when things are spaced out rather than crammed together, and storage/bandwidth/compile time is not a concern.
The quick summary of the below table is:
0 or 1 blank line between fields
2 blank lines between functions and other such blocks
3 blank lines between classes and other types
Place Number of spaces Good Bad
Before opening comment
(copyright, file documentation, etc.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//
// MyFile.swift
// Project Name
//
// Created by Ben Leggiero on 2019-07-16
// Copyright © 2019 Ben Leggiero. All rights reserved.
//
import Cocoa
import FancySDK
let defaultFooSize = 5
fileprivate var instanceCount = 0
class Foo {
private var usageCount = 0
let size : Int
var intValue : Int {
return usageCount + size
}
// MARK: Initialization
init ( size : Int ) {
instanceCount += 1
self . size = size
}
convenience init () {
self . init ( size : defaultFooSize )
}
// MARK: Class-specific functions
func bar () {
print ( "Bar!" )
usageCount += 1
}
func handleWithBaz ( text : String ) {
if let baz = FancySDK . baz {
let hogeText = text . hoge ()
baz . handle ( hogeText )
}
print ( "Did handle baz" )
usageCount += 1
}
}
// MARK: - Extensions
extension String {
func hoge () -> String {
return self + " - Hoge"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//
// MyFile.swift
// Project Name
//
// Created by Ben Leggiero on 2019-07-16
// Copyright © 2019 Ben Leggiero. All rights reserved.
//
import Cocoa
import FancySDK
let defaultFooSize = 5
fileprivate var instanceCount = 0
class Foo {
private var usageCount = 0
let size : Int
var intValue : Int {
return usageCount + size
}
// MARK: Initialization
init ( size : Int ) {
instanceCount += 1
self . size = size
}
convenience init () {
self . init ( size : defaultFooSize )
}
// MARK: Class-specific functions
func bar () {
print ( "Bar!" )
usageCount += 1
}
func handleWithBaz ( text : String ) {
if let baz = FancySDK . baz {
let hogeText = text . hoge ()
baz . handle ( hogeText )
}
print ( "Did handle baz" )
usageCount += 1
}
}
// MARK: - Extensions
extension String {
func hoge () -> String {
return self + " - Hoge"
}
}
Between opening comment and group of imports
After group of imports
Depending on following number of variables/constants outside scope
Around group of variables/constants outside scope
Depending on number of variables/constants outside scope
Around types (classes, enums, etc.)
At beginning of type
After opening brace and before actual code
0 or 1
Depending on preference
Around functions and other scoped blocks
At beginning of functions and other scoped blocks
After opening brace and before actual code
Depending on preference
At the end of functions and other scoped blocks
Around variables
Depending on complexity of declaration
Around local blocks (if
, closures, etc.)
Before // MARK:
Before // MARK: -
After // MARK:
and // MARK: -
Line breaks
Place Number of spaces Good Bad
After type declaration attribute
After function attribute
After member attribute
@objc
class Foo : NSObject {
@objc
@IBAction
func bar ( _ sender : Any ?) {
// Content...
}
@objc ( baz )
var qux : Hoge ? = nil
func norf ( callback : @escaping () -> Void ) {
// Content...
}
}
@objc class Foo : NSObject {
@objc @IBAction
func bar ( _ sender : Any ?) {
// Content...
}
@objc ( baz )
var qux : Hoge ? = nil
func norf ( callback : @escaping
() -> Void ) {
// Content...
}
}