| --- |
| layout: page |
| title: Swift Style Guide |
| --- |
| <!-- {% comment %} |
| The width of <pre> elements on this page is carefully regulated, so we |
| can afford to drop the scrollbar boxes. |
| {% endcomment %} --> |
| <style> |
| article pre { |
| overflow: visible; |
| } |
| </style> |
| |
| This style guide is based on Apple's excellent Swift standard library style and |
| also incorporates feedback from usage across multiple Swift projects within |
| Google. It is a living document and the basis upon which the formatter is |
| implemented. |
| |
| ## Table of Contents |
| {:.no_toc} |
| |
| * TOC |
| {:toc} |
| |
| ## Source File Basics |
| |
| ### File Names |
| |
| All Swift source files end with the extension `.swift`. |
| |
| In general, the name of a source file best describes the primary entity that it |
| contains. A file that primarily contains a single type has the name of that |
| type. A file that extends an existing type with protocol conformance is named |
| with a combination of the type name and the protocol name, joined with a plus |
| (`+`) sign. For more complex situations, exercise your best judgment. |
| |
| For example, |
| |
| * A file containing a single type `MyType` is named `MyType.swift`. |
| * A file containing a type `MyType` and some top-level helper functions is also |
| named `MyType.swift`. (The top-level helpers are not the primary entity.) |
| * A file containing a single extension to a type `MyType` that adds conformance |
| to a protocol `MyProtocol` is named `MyType+MyProtocol.swift`. |
| * A file containing multiple extensions to a type `MyType` that add |
| conformances, nested types, or other functionality to a type can be named more |
| generally, as long as it is prefixed with `MyType+`; for example, |
| `MyType+Additions.swift`. |
| * A file containing related declarations that are not otherwise scoped under a |
| common type or namespace (such as a collection of global mathematical |
| functions) can be named descriptively; for example, `Math.swift`. |
| |
| ### File Encoding |
| |
| Source files are encoded in UTF-8. |
| |
| ### Whitespace Characters |
| |
| Aside from the line terminator, the Unicode horizontal space character |
| (`U+0020`) is the only whitespace character that appears anywhere in a source |
| file. The implications are: |
| |
| * All other whitespace characters in string and character literals are |
| represented by their corresponding escape sequence. |
| * Tab characters are not used for indentation. |
| |
| ### Special Escape Sequences |
| |
| For any character that has a special escape sequence (`\t`, `\n`, `\r`, `\"`, |
| `\'`, `\\`, and `\0`), that sequence is used rather than the equivalent Unicode |
| (e.g., `\u{000a}`) escape sequence. |
| |
| ### Invisible Characters and Modifiers |
| |
| Invisible characters, such as the zero width space and other control characters |
| that do not affect the graphical representation of a string, are always written |
| as Unicode escape sequences. |
| |
| Control characters, combining characters, and variation selectors that _do_ |
| affect the graphical representation of a string are not escaped when they are |
| attached to a character or characters that they modify. If such a Unicode scalar |
| is present in isolation or is otherwise not modifying another character in the |
| same string, it is written as a Unicode escape sequence. |
| |
| The strings below are well-formed because the umlauts and variation selectors |
| associate with neighboring characters in the string. The second example is in |
| fact composed of _five_ Unicode scalars, but they are unescaped because the |
| specific combination is rendered as a single character. |
| |
| ~~~ swift |
| let size = "Übergröße" |
| let shrug = "🤷🏿️" |
| ~~~ |
| {:.good} |
| |
| In the example below, the umlaut and variation selector are in strings by |
| themselves, so they are escaped. |
| |
| ~~~ swift |
| let diaeresis = "\u{0308}" |
| let skinToneType6 = "\u{1F3FF}" |
| ~~~ |
| {:.good} |
| |
| If the umlaut were included in the string literally, it would combine with |
| the preceding quotation mark, impairing readability. Likewise, while most |
| systems may render a standalone skin tone modifier as a block graphic, the |
| example below is still forbidden because it is a modifier that is not modifying |
| a character in the same string. |
| |
| ~~~ swift |
| let diaeresis = "̈" |
| let skinToneType6 = "🏿" |
| ~~~ |
| {:.bad} |
| |
| ### String Literals |
| |
| Unicode escape sequences (`\u{????}`) and literal code points (for example, `Ü`) |
| outside the 7-bit ASCII range are never mixed in the same string. |
| |
| More specifically, string literals are either: |
| |
| * composed of a combination of Unicode code points written literally and/or |
| single character escape sequences (such as `\t`, but _not_ `\u{????}`), or |
| * composed of 7-bit ASCII with any number of Unicode escape sequences and/or |
| other escape sequences. |
| |
| The following example is correct because `\n` is allowed to be present among |
| other Unicode code points. |
| |
| ~~~ swift |
| let size = "Übergröße\n" |
| ~~~ |
| {:.good} |
| |
| The following example is allowed because it follows the rules above, but it is |
| _not preferred_ because the text is harder to read and understand compared to |
| the string above. |
| |
| ~~~ swift |
| let size = "\u{00DC}bergr\u{00F6}\u{00DF}e\n" |
| ~~~ |
| {:.good} |
| |
| The example below is forbidden because it mixes code points outside the 7-bit |
| ASCII range in both literal form and in escaped form. |
| |
| ~~~ swift |
| let size = "Übergr\u{00F6}\u{00DF}e\n" |
| ~~~ |
| {:.bad} |
| |
| > **Aside:** Never make your code less readable simply out of fear |
| > that some programs might not handle non-ASCII characters properly. If that |
| > should happen, those programs are broken and must be fixed. |
| |
| ## Source File Structure |
| |
| ### File Comments |
| |
| Comments describing the contents of a source file are optional. They are |
| discouraged for files that contain only a single abstraction (such as a class |
| declaration)—in those cases, the documentation comment on the abstraction |
| itself is sufficient and a file comment is only present if it provides |
| additional useful information. File comments are allowed for files that contain |
| multiple abstractions in order to document that grouping as a whole. |
| |
| ### Import Statements |
| |
| A source file imports exactly the top-level modules that it needs; nothing more |
| and nothing less. If a source file uses definitions from both `UIKit` and |
| `Foundation`, it imports both explicitly; it does not rely on the fact that some |
| Apple frameworks transitively import others as an implementation detail. |
| |
| Imports of whole modules are preferred to imports of individual declarations or |
| submodules. |
| |
| > There are a number of reasons to avoid importing individual members: |
| > |
| > * There is no automated tooling to resolve/organize imports. |
| > * Existing automated tooling (such as Xcode's migrator) are less likely to |
| > work well on code that imports individual members because they are |
| > considered corner cases. |
| > * The prevailing style in Swift (based on official examples and community |
| > code) is to import entire modules. |
| |
| Imports of individual declarations are permitted when importing the whole module |
| would otherwise pollute the global namespace with top-level definitions (such as |
| C interfaces). Use your best judgment in these situations. |
| |
| Imports of submodules are permitted if the submodule exports functionality that |
| is not available when importing the top-level module. For example, |
| `UIKit.UIGestureRecognizerSubclass` must be imported explicitly to expose the |
| methods that allow client code to subclass `UIGestureRecognizer`—those are |
| not visible by importing `UIKit` alone. |
| |
| Import statements are not line-wrapped. |
| |
| Import statements are the first non-comment tokens in a source file. They are |
| grouped in the following fashion, with the imports in each group ordered |
| lexicographically and with exactly one blank line between each group: |
| |
| 1. Module/submodule imports not under test |
| 1. Individual declaration imports (`class`, `enum`, `func`, `struct`, `var`) |
| 1. Modules imported with `@testable` (only present in test sources) |
| |
| ~~~ swift |
| import CoreLocation |
| import MyThirdPartyModule |
| import SpriteKit |
| import UIKit |
| |
| import func Darwin.C.isatty |
| |
| @testable import MyModuleUnderTest |
| ~~~ |
| {:.good} |
| |
| ### Type, Variable, and Function Declarations |
| |
| In general, most source files contain only one top-level type, especially when |
| the type declaration is large. Exceptions are allowed when it makes sense to |
| include multiple related types in a single file. For example, |
| |
| * A class and its delegate protocol may be defined in the same file. |
| * A type and its small related helper types may be defined in the same file. |
| This can be useful when using `fileprivate` to restrict certain functionality |
| of the type and/or its helpers to only that file and not the rest of the |
| module. |
| |
| The order of types, variables, and functions in a source file, and the order of |
| the members of those types, can have a great effect on readability. However, |
| there is no single correct recipe for how to do it; different files and |
| different types may order their contents in different ways. |
| |
| What is important is that each file and type uses _**some** logical order,_ |
| which its maintainer could explain if asked. For example, new methods are not |
| just habitually added to the end of the type, as that would yield "chronological |
| by date added" ordering, which is not a logical ordering. |
| |
| When deciding on the logical order of members, it can be helpful for readers and |
| future writers (including yourself) to use `// MARK:` comments to provide |
| descriptions for that grouping. These comments are also interpreted by Xcode and |
| provide bookmarks in the source window's navigation bar. (Likewise, |
| `// MARK: - `, written with a hyphen before the description, causes Xcode to |
| insert a divider before the menu item.) For example, |
| |
| ~~~ swift |
| class MovieRatingViewController: UITableViewController { |
| |
| // MARK: - View controller lifecycle methods |
| |
| override func viewDidLoad() { |
| // ... |
| } |
| |
| override func viewWillAppear(_ animated: Bool) { |
| // ... |
| } |
| |
| // MARK: - Movie rating manipulation methods |
| |
| @objc private func ratingStarWasTapped(_ sender: UIButton?) { |
| // ... |
| } |
| |
| @objc private func criticReviewWasTapped(_ sender: UIButton?) { |
| // ... |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| ### Overloaded Declarations |
| |
| When a type has multiple initializers or subscripts, or a file/type has multiple |
| functions with the same base name (though perhaps with different argument |
| labels), _and_ when these overloads appear in the same type or extension scope, |
| they appear sequentially with no other code in between. |
| |
| ### Extensions |
| |
| Extensions can be used to organize functionality of a type across multiple |
| "units." As with member order, the organizational structure/grouping you choose |
| can have a great effect on readability; you must use _**some** logical |
| organizational structure_ that you could explain to a reviewer if asked. |
| |
| ## General Formatting |
| |
| ### Column Limit |
| |
| Swift code has a column limit of 100 characters. Except as noted below, any line |
| that would exceed this limit must be line-wrapped as described in |
| [Line-Wrapping](#line-wrapping). |
| |
| **Exceptions:** |
| |
| 1. Lines where obeying the column limit is not possible without breaking a |
| meaningful unit of text that should not be broken (for example, a long URL in |
| a comment). |
| 1. `import` statements. |
| 1. Code generated by another tool. |
| |
| ### Braces |
| |
| In general, braces follow Kernighan and Ritchie (K&R) style for non-empty |
| blocks with exceptions for Swift-specific constructs and rules: |
| |
| * There **is no** line break before the opening brace (`{`), **unless** required |
| by application of the rules in [Line-Wrapping](#line-wrapping). |
| * There **is a** line break after the opening brace (`{`), except |
| * in closures, where the signature of the closure is placed on the same line |
| as the curly brace, if it fits, and a line break follows the `in` keyword. |
| * where it may be omitted as described in |
| [One Statement Per Line](#one-statement-per-line). |
| * empty blocks may be written as `{}`. |
| * There **is a** line break before the closing brace (`}`), except where it may |
| be omitted as described in [One Statement Per Line](#one-statement-per-line), |
| or it completes an empty block. |
| * There **is a** line break after the closing brace (`}`), **if and only if** |
| that brace terminates a statement or the body of a declaration. For example, |
| an `else` block is written `} else {` with both braces on the same line. |
| |
| ### Semicolons |
| |
| Semicolons (`;`) are **not used**, either to terminate or separate statements. |
| |
| In other words, the only location where a semicolon may appear is inside a |
| string literal or a comment. |
| |
| ~~~ swift |
| func printSum(_ a: Int, _ b: Int) { |
| let sum = a + b |
| print(sum) |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| func printSum(_ a: Int, _ b: Int) { |
| let sum = a + b; |
| print(sum); |
| } |
| ~~~ |
| {:.bad} |
| |
| ### One Statement Per Line |
| |
| There is **at most** one statement per line, and each statement is followed by a |
| line break, except when the line ends with a block that also contains zero |
| or one statements. |
| |
| ~~~ swift |
| guard let value = value else { return 0 } |
| |
| defer { file.close() } |
| |
| switch someEnum { |
| case .first: return 5 |
| case .second: return 10 |
| case .third: return 20 |
| } |
| |
| let squares = numbers.map { $0 * $0 } |
| |
| var someProperty: Int { |
| get { return otherObject.property } |
| set { otherObject.property = newValue } |
| } |
| |
| var someProperty: Int { return otherObject.somethingElse() } |
| |
| required init?(coder aDecoder: NSCoder) { fatalError("no coder") } |
| ~~~ |
| {:.good} |
| |
| Wrapping the body of a single-statement block onto its own line is always |
| allowed. Exercise best judgment when deciding whether to place a conditional |
| statement and its body on the same line. For example, single line conditionals |
| work well for early-return and basic cleanup tasks, but less so when the body |
| contains a function call with significant logic. When in doubt, write it as a |
| multi-line statement. |
| |
| ### Line-Wrapping |
| |
| > Terminology note: **Line-wrapping** is the activity of dividing code into |
| > multiple lines that might otherwise legally occupy a single line. |
| |
| For the purposes of Google Swift style, many declarations (such as type |
| declarations and function declarations) and other expressions (like function |
| calls) can be partitioned into **breakable** units that are separated by |
| **unbreakable** delimiting token sequences. |
| |
| As an example, consider the following complex function declaration, which needs |
| to be line-wrapped: |
| |
| ~~~ swift |
| public func index<Elements: Collection, Element>(of element: Element, in collection: Elements) -> Elements.Index? where Elements.Element == Element, Element: Equatable { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| This declaration is split as follows (scroll horizontally if necessary to see |
| the full example). Unbreakable token sequences are indicated in orange; |
| breakable sequences are indicated in blue. |
| |
| <pre class="lw-container lw-container-numbered"> |
| <span class="lw-ub">public func index<</span><span class="lw-br">Elements: Collection, Element</span><span class="lw-ub">>(</span><span class="lw-br">of element: Element, in collection: Elements</span><span class="lw-ub">) -></span><span class="lw-br">Elements.Index?</span><span class="lw-ub">where</span><span class="lw-br">Elements.Element == Element, Element: Equatable</span>{ |
| // ... |
| } |
| </pre> |
| |
| 1. The **unbreakable** token sequence up through the open angle bracket (`<`) |
| that begins the generic argument list. |
| 1. The **breakable** list of generic arguments. |
| 1. The **unbreakable** token sequence (`>(`) that separates the generic |
| arguments from the formal arguments. |
| 1. The **breakable** comma-delimited list of formal arguments. |
| 1. The **unbreakable** token-sequence from the closing parenthesis (`)`) up |
| through the arrow (`->`) that precedes the return type. |
| 1. The **breakable** return type. |
| 1. The **unbreakable** `where` keyword that begins the generic constraints list. |
| 1. The **breakable** comma-delimited list of generic constraints. |
| |
| Using these concepts, the cardinal rules of Google Swift style for line-wrapping |
| are: |
| |
| 1. If the entire declaration, statement, or expression fits on one line, then do |
| that. |
| 1. Comma-delimited lists are only laid out in one direction: horizontally or |
| vertically. In other words, all elements must fit on the same line, or each |
| element must be on its own line. A horizontally-oriented list does not |
| contain any line breaks, even before the first element or after the last |
| element. Except in control flow statements, a vertically-oriented list |
| contains a line break before the first element and after each element. |
| 1. A continuation line starting with an unbreakable token sequence is indented |
| at the same level as the original line. |
| 1. A continuation line that is part of a vertically-oriented comma-delimited |
| list is indented exactly +2 from the original line. |
| 1. When an open curly brace (`{`) follows a line-wrapped declaration or |
| expression, it is on the same line as the final continuation line unless that |
| line is indented at +2 from the original line. In that case, the brace is |
| placed on its own line, to avoid the continuation lines from blending |
| visually with the body of the subsequent block. |
| |
| ~~~ swift |
| public func index<Elements: Collection, Element>( |
| of element: Element, |
| in collection: Elements |
| ) -> Elements.Index? |
| where |
| Elements.Element == Element, |
| Element: Equatable |
| { // GOOD. |
| for current in elements { |
| // ... |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| public func index<Elements: Collection, Element>( |
| of element: Element, |
| in collection: Elements |
| ) -> Elements.Index? |
| where |
| Elements.Element == Element, |
| Element: Equatable { // AVOID. |
| for current in elements { |
| // ... |
| } |
| } |
| ~~~ |
| {:.bad} |
| |
| For declarations that contain a `where` clause followed by generic constraints, |
| additional rules apply: |
| |
| 1. If the generic constraint list exceeds the column limit when placed on the |
| same line as the return type, then a line break is first inserted **before** |
| the `where` keyword and the `where` keyword is indented at the same level as |
| the original line. |
| 1. If the generic constraint list still exceeds the column limit after inserting |
| the line break above, then the constraint list is oriented vertically with a |
| line break after the `where` keyword and a line break after the final |
| constraint. |
| |
| Concrete examples of this are shown in the relevant subsections below. |
| |
| This line-wrapping style ensures that the different parts of a declaration are |
| _quickly and easily identifiable to the reader_ by using indentation and line |
| breaks, while also preserving the same indentation level for those parts |
| throughout the file. Specifically, it prevents the zig-zag effect that would be |
| present if the arguments are indented based on opening parentheses, as is common |
| in other languages: |
| |
| ~~~ swift |
| public func index<Elements: Collection, Element>(of element: Element, // AVOID. |
| in collection: Elements) -> Elements.Index? |
| where Elements.Element == Element, Element: Equatable { |
| doSomething() |
| } |
| ~~~ |
| {:.bad} |
| |
| #### Function Declarations |
| |
| <pre class="lw-container"> |
| <span class="lw-ub"><em>modifiers</em> func <em>name</em>(</span><span class="lw-br"><em>formal arguments</em></span><span class="lw-ub">)</span>{ |
| |
| <span class="lw-ub"><em>modifiers</em> func <em>name</em>(</span><span class="lw-br"><em>formal arguments</em></span><span class="lw-ub">) -></span><span class="lw-br"><em>result</em></span>{ |
| |
| <span class="lw-ub"><em>modifiers</em> func <em>name</em><</span><span class="lw-br"><em>generic arguments</em></span><span class="lw-ub">>(</span><span class="lw-br"><em>formal arguments</em></span><span class="lw-ub">) throws -></span><span class="lw-br"><em>result</em></span>{ |
| |
| <span class="lw-ub"><em>modifiers</em> func <em>name</em><</span><span class="lw-br"><em>generic arguments</em></span><span class="lw-ub">>(</span><span class="lw-br"><em>formal arguments</em></span><span class="lw-ub">) throws -></span><span class="lw-br"><em>result</em></span><span class="lw-ub">where</span><span class="lw-br"><em>generic constraints</em></span>{ |
| </pre> |
| |
| Applying the rules above from left to right gives us the following |
| line-wrapping: |
| |
| ~~~ swift |
| public func index<Elements: Collection, Element>( |
| of element: Element, |
| in collection: Elements |
| ) -> Elements.Index? where Elements.Element == Element, Element: Equatable { |
| for current in elements { |
| // ... |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| Function declarations in protocols that are terminated with a closing |
| parenthesis (`)`) may place the parenthesis on the same line as the final |
| argument **or** on its own line. |
| |
| ~~~ swift |
| public protocol ContrivedExampleDelegate { |
| func contrivedExample( |
| _ contrivedExample: ContrivedExample, |
| willDoSomethingTo someValue: SomeValue) |
| } |
| |
| public protocol ContrivedExampleDelegate { |
| func contrivedExample( |
| _ contrivedExample: ContrivedExample, |
| willDoSomethingTo someValue: SomeValue |
| ) |
| } |
| ~~~ |
| {:.good} |
| |
| If types are complex and/or deeply nested, individual elements in the |
| arguments/constraints lists and/or the return type may also need to be wrapped. |
| In these rare cases, the same line-wrapping rules apply to those parts as apply |
| to the declaration itself. |
| |
| ~~~ swift |
| public func performanceTrackingIndex<Elements: Collection, Element>( |
| of element: Element, |
| in collection: Elements |
| ) -> ( |
| Element.Index?, |
| PerformanceTrackingIndexStatistics.Timings, |
| PerformanceTrackingIndexStatistics.SpaceUsed |
| ) { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| However, `typealias`es or some other means are often a better way to simplify |
| complex declarations whenever possible. |
| |
| #### Type and Extension Declarations |
| |
| The examples below apply equally to `class`, `struct`, `enum`, `extension`, and |
| `protocol` (with the obvious exception that all but the first do not have |
| superclasses in their inheritance list, but they are otherwise structurally |
| similar). |
| |
| <pre class="lw-container"> |
| <span class="lw-ub"><em>modifiers</em> class <em>Name</em></span>{ |
| |
| <span class="lw-ub"><em>modifiers</em> class <em>Name</em>:</span><span class="lw-br"><em>superclass and protocols</em></span>{ |
| |
| <span class="lw-ub"><em>modifiers</em> class <em>Name</em><</span><span class="lw-br"><em>generic arguments</em></span><span class="lw-ub">>:</span><span class="lw-br"><em>superclass and protocols</em></span>{ |
| |
| <span class="lw-ub"><em>modifiers</em> class <em>Name</em><</span><span class="lw-br"><em>generic arguments</em></span><span class="lw-ub">>:</span><span class="lw-br"><em>superclass and protocols</em></span><span class="lw-ub">where</span><span class="lw-br"><em>generic constraints</em></span>{ |
| </pre> |
| |
| ~~~ swift |
| class MyClass: |
| MySuperclass, |
| MyProtocol, |
| SomeoneElsesProtocol, |
| SomeFrameworkProtocol |
| { |
| // ... |
| } |
| |
| class MyContainer<Element>: |
| MyContainerSuperclass, |
| MyContainerProtocol, |
| SomeoneElsesContainerProtocol, |
| SomeFrameworkContainerProtocol |
| { |
| // ... |
| } |
| |
| class MyContainer<BaseCollection>: |
| MyContainerSuperclass, |
| MyContainerProtocol, |
| SomeoneElsesContainerProtocol, |
| SomeFrameworkContainerProtocol |
| where BaseCollection: Collection { |
| // ... |
| } |
| |
| class MyContainer<BaseCollection>: |
| MyContainerSuperclass, |
| MyContainerProtocol, |
| SomeoneElsesContainerProtocol, |
| SomeFrameworkContainerProtocol |
| where |
| BaseCollection: Collection, |
| BaseCollection.Element: Equatable, |
| BaseCollection.Element: SomeOtherProtocolOnlyUsedToForceLineWrapping |
| { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| #### Function Calls |
| |
| When a function call is line-wrapped, each argument is written on its own line, |
| indented +2 from the original line. |
| |
| As with function declarations, if the function call terminates its enclosing |
| statement and ends with a closing parenthesis (`)`) (that is, it has no trailing |
| closure), then the parenthesis may be placed **either** on the same line as the |
| final argument **or** on its own line. |
| |
| ~~~ swift |
| let index = index( |
| of: veryLongElementVariableName, |
| in: aCollectionOfElementsThatAlsoHappensToHaveALongName) |
| |
| let index = index( |
| of: veryLongElementVariableName, |
| in: aCollectionOfElementsThatAlsoHappensToHaveALongName |
| ) |
| ~~~ |
| {:.good} |
| |
| If the function call ends with a trailing closure and the closure's signature |
| must be wrapped, then place it on its own line and wrap the argument list in |
| parentheses to distinguish it from the body of the closure below it. |
| |
| ~~~ swift |
| someAsynchronousAction.execute(withDelay: howManySeconds, context: actionContext) { |
| (context, completion) in |
| doSomething(withContext: context) |
| completion() |
| } |
| ~~~ |
| {:.good} |
| |
| #### Control Flow Statements |
| |
| When a control flow statement (such as `if`, `guard`, `while`, or `for`) is |
| wrapped, the first continuation line is indented to the same position as the |
| token following the control flow keyword. Additional continuation lines are |
| indented at that same position if they are syntactically parallel elements, or |
| in +2 increments from that position if they are syntactically nested. |
| |
| The open brace (`{`) preceding the body of the control flow statement can either |
| be placed on the same line as the last continuation line or on the next line, |
| at the same indentation level as the beginning of the statement. For `guard` |
| statements, the `else {` must be kept together, either on the same line or on |
| the next line. |
| |
| ~~~ swift |
| if aBooleanValueReturnedByAVeryLongOptionalThing() && |
| aDifferentBooleanValueReturnedByAVeryLongOptionalThing() && |
| yetAnotherBooleanValueThatContributesToTheWrapping() { |
| doSomething() |
| } |
| |
| if aBooleanValueReturnedByAVeryLongOptionalThing() && |
| aDifferentBooleanValueReturnedByAVeryLongOptionalThing() && |
| yetAnotherBooleanValueThatContributesToTheWrapping() |
| { |
| doSomething() |
| } |
| |
| if let value = aValueReturnedByAVeryLongOptionalThing(), |
| let value2 = aDifferentValueReturnedByAVeryLongOptionalThing() { |
| doSomething() |
| } |
| |
| if let value = aValueReturnedByAVeryLongOptionalThing(), |
| let value2 = aDifferentValueReturnedByAVeryLongOptionalThingThatForcesTheBraceToBeWrapped() |
| { |
| doSomething() |
| } |
| |
| guard let value = aValueReturnedByAVeryLongOptionalThing(), |
| let value2 = aDifferentValueReturnedByAVeryLongOptionalThing() else { |
| doSomething() |
| } |
| |
| guard let value = aValueReturnedByAVeryLongOptionalThing(), |
| let value2 = aDifferentValueReturnedByAVeryLongOptionalThing() |
| else { |
| doSomething() |
| } |
| |
| for element in collection |
| where element.happensToHaveAVeryLongPropertyNameThatYouNeedToCheck { |
| doSomething() |
| } |
| ~~~ |
| {:.good} |
| |
| #### Other Expressions |
| |
| When line-wrapping other expressions that are not function calls (as described |
| above), the second line (the one immediately following the first break) is |
| indented exactly +2 from the original line. |
| |
| When there are multiple continuation lines, indentation may be varied in |
| increments of +2 as needed. In general, two continuation lines use the same |
| indentation level if and only if they begin with syntactically parallel |
| elements. However, if there are many continuation lines caused by long wrapped |
| expressions, consider splitting them into multiple statements using temporary |
| variables when possible. |
| |
| ~~~ swift |
| let result = anExpression + thatIsMadeUpOf * aLargeNumber + |
| ofTerms / andTherefore % mustBeWrapped + ( |
| andWeWill - keepMakingItLonger * soThatWeHave / aContrivedExample) |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let result = anExpression + thatIsMadeUpOf * aLargeNumber + |
| ofTerms / andTherefore % mustBeWrapped + ( |
| andWeWill - keepMakingItLonger * soThatWeHave / aContrivedExample) |
| ~~~ |
| {:.bad} |
| |
| ### Horizontal Whitespace |
| |
| > **Terminology note:** In this section, _horizontal whitespace_ refers to |
| > _interior_ space. These rules are never interpreted as requiring or forbidding |
| > additional space at the start of a line. |
| |
| Beyond where required by the language or other style rules, and apart from |
| literals and comments, a single Unicode space also appears in the following |
| places **only**: |
| |
| 1. Separating any reserved word starting a conditional or switch statement (such |
| as `if`, `guard`, `while`, or `switch`) from the expression that follows it |
| if that expression starts with an open parenthesis (`(`). |
| |
| ~~~ swift |
| if (x == 0 && y == 0) || z == 0 { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| if(x == 0 && y == 0) || z == 0 { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| 1. Before any closing curly brace (`}`) that follows code on the same line, |
| before any open curly brace (`{`), and after any open curly brace (`{`) that |
| is followed by code on the same line. |
| |
| ~~~ swift |
| let nonNegativeCubes = numbers.map { $0 * $0 * $0 }.filter { $0 >= 0 } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let nonNegativeCubes = numbers.map { $0 * $0 * $0 } .filter { $0 >= 0 } |
| let nonNegativeCubes = numbers.map{$0 * $0 * $0}.filter{$0 >= 0} |
| ~~~ |
| {:.bad} |
| |
| 1. _On both sides_ of any binary or ternary operator, including the |
| "operator-like" symbols described below, with exceptions noted at the end: |
| |
| 1. The `=` sign used in assignment, initialization of variables/properties, |
| and default arguments in functions. |
| |
| ~~~ swift |
| var x = 5 |
| |
| func sum(_ numbers: [Int], initialValue: Int = 0) { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| var x=5 |
| |
| func sum(_ numbers: [Int], initialValue: Int=0) { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| 1. The ampersand (`&`) in a protocol composition type. |
| |
| ~~~ swift |
| func sayHappyBirthday(to person: NameProviding & AgeProviding) { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| func sayHappyBirthday(to person: NameProviding&AgeProviding) { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| 1. The operator symbol in a function declaring/implementing that operator. |
| |
| ~~~ swift |
| static func == (lhs: MyType, rhs: MyType) -> Bool { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| static func ==(lhs: MyType, rhs: MyType) -> Bool { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| 1. The arrow (`->`) preceding the return type of a function. |
| |
| ~~~ swift |
| func sum(_ numbers: [Int]) -> Int { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| func sum(_ numbers: [Int])->Int { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| 1. **Exception:** There is no space on either side of the dot (`.`) used to |
| reference value and type members. |
| |
| ~~~ swift |
| let width = view.bounds.width |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let width = view . bounds . width |
| ~~~ |
| {:.bad} |
| |
| 1. **Exception:** There is no space on either side of the `..<` or `...` |
| operators used in range expressions. |
| |
| ~~~ swift |
| for number in 1...5 { |
| // ... |
| } |
| |
| let substring = string[index..<string.endIndex] |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| for number in 1 ... 5 { |
| // ... |
| } |
| |
| let substring = string[index ..< string.endIndex] |
| ~~~ |
| {:.bad} |
| |
| 1. After, but not before, the comma (`,`) in parameter lists and in |
| tuple/array/dictionary literals. |
| |
| ~~~ swift |
| let numbers = [1, 2, 3] |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let numbers = [1,2,3] |
| let numbers = [1 ,2 ,3] |
| let numbers = [1 , 2 , 3] |
| ~~~ |
| {:.bad} |
| |
| 1. After, but not before, the colon (`:`) in |
| |
| 1. Superclass/protocol conformance lists and generic constraints. |
| |
| ~~~ swift |
| struct HashTable: Collection { |
| // ... |
| } |
| |
| struct AnyEquatable<Wrapped: Equatable>: Equatable { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| struct HashTable : Collection { |
| // ... |
| } |
| |
| struct AnyEquatable<Wrapped : Equatable> : Equatable { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| 1. Function argument labels and tuple element labels. |
| |
| ~~~ swift |
| let tuple: (x: Int, y: Int) |
| |
| func sum(_ numbers: [Int]) { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let tuple: (x:Int, y:Int) |
| let tuple: (x : Int, y : Int) |
| |
| func sum(_ numbers:[Int]) { |
| // ... |
| } |
| |
| func sum(_ numbers : [Int]) { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| 1. Variable/property declarations with explicit types. |
| |
| ~~~ swift |
| let number: Int = 5 |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let number:Int = 5 |
| let number : Int = 5 |
| ~~~ |
| {:.bad} |
| |
| 1. Shorthand dictionary type names. |
| |
| ~~~ swift |
| var nameAgeMap: [String: Int] = [] |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| var nameAgeMap: [String:Int] = [] |
| var nameAgeMap: [String : Int] = [] |
| ~~~ |
| {:.bad} |
| |
| 1. Dictionary literals. |
| |
| ~~~ swift |
| let nameAgeMap = ["Ed": 40, "Timmy": 9] |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let nameAgeMap = ["Ed":40, "Timmy":9] |
| let nameAgeMap = ["Ed" : 40, "Timmy" : 9] |
| ~~~ |
| {:.bad} |
| |
| 1. At least two spaces before and exactly one space after the double slash |
| (`//`) that begins an end-of-line comment. |
| |
| ~~~ swift |
| let initialFactor = 2 // Warm up the modulator. |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let initialFactor = 2 // Warm up the modulator. |
| ~~~ |
| {:.bad} |
| |
| 1. Outside, but not inside, the brackets of an array or dictionary literals and |
| the parentheses of a tuple literal. |
| |
| ~~~ swift |
| let numbers = [1, 2, 3] |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let numbers = [ 1, 2, 3 ] |
| ~~~ |
| {:.bad} |
| |
| ### Horizontal Alignment |
| |
| > **Terminology note:** _Horizontal alignment_ is the practice of adding a |
| > variable number of additional spaces in your code with the goal of making |
| > certain tokens appear directly below certain other tokens on previous lines. |
| |
| Horizontal alignment is forbidden except when writing obviously tabular data |
| where omitting the alignment would be harmful to readability. In other cases |
| (for example, lining up the types of stored property declarations in a `struct` |
| or `class`), horizontal alignment is an invitation for maintenance problems if a |
| new member is introduced that requires every other member to be realigned. |
| |
| ~~~ swift |
| struct DataPoint { |
| var value: Int |
| var primaryColor: UIColor |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| struct DataPoint { |
| var value: Int |
| var primaryColor: UIColor |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Vertical Whitespace |
| |
| A single blank line appears in the following locations: |
| |
| 1. Between consecutive members of a type: properties, initializers, methods, |
| enum cases, and nested types, **except that**: |
| |
| 1. A blank line is optional between two consecutive stored properties or two |
| enum cases whose declarations fit entirely on a single line. Such blank |
| lines can be used to create _logical groupings_ of these declarations. |
| 1. A blank line is optional between two extremely closely related properties |
| that do not otherwise meet the criterion above; for example, a private |
| stored property and a related public computed property. |
| |
| 1. _Only as needed_ between statements to organize code into logical |
| subsections. |
| 1. _Optionally_ before the first member or after the last member of a type |
| (neither is encouraged nor discouraged). |
| 1. Anywhere explicitly required by other sections of this document. |
| |
| _Multiple_ blank lines are permitted, but never required (nor encouraged). If |
| you do use multiple consecutive blank lines, do so consistently throughout your |
| code base. |
| |
| ### Parentheses |
| |
| Parentheses are **not** used around the top-most expression that follows an |
| `if`, `guard`, `while`, or `switch` keyword. |
| |
| ~~~ swift |
| if x == 0 { |
| print("x is zero") |
| } |
| |
| if (x == 0 || y == 1) && z == 2 { |
| print("...") |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| if (x == 0) { |
| print("x is zero") |
| } |
| |
| if ((x == 0 || y == 1) && z == 2) { |
| print("...") |
| } |
| ~~~ |
| {:.bad} |
| |
| Optional grouping parentheses are omitted only when the author and the reviewer |
| agree that there is no reasonable chance that the code will be misinterpreted |
| without them, nor that they would have made the code easier to read. It is _not_ |
| reasonable to assume that every reader has the entire Swift operator precedence |
| table memorized. |
| |
| ## Formatting Specific Constructs |
| |
| ### Non-Documentation Comments |
| |
| Non-documentation comments always use the double-slash format (`//`), never the |
| C-style block format (`/* ... */`). |
| |
| ### Properties |
| |
| Local variables are declared close to the point at which they are first used |
| (within reason) to minimize their scope. |
| |
| With the exception of tuple destructuring, every `let` or `var` statement |
| (whether a property or a local variable) declares exactly one variable. |
| |
| ~~~ swift |
| var a = 5 |
| var b = 10 |
| |
| let (quotient, remainder) = divide(100, 9) |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| var a = 5, b = 10 |
| ~~~ |
| {:.bad} |
| |
| ### Switch Statements |
| |
| Case statements are indented at the _same_ level as the switch statement to |
| which they belong; the statements inside the case blocks are then indented +2 |
| spaces from that level. |
| |
| ~~~ swift |
| switch order { |
| case .ascending: |
| print("Ascending") |
| case .descending: |
| print("Descending") |
| case .same: |
| print("Same") |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| switch order { |
| case .ascending: |
| print("Ascending") |
| case .descending: |
| print("Descending") |
| case .same: |
| print("Same") |
| } |
| ~~~ |
| {:.bad} |
| |
| ~~~ swift |
| switch order { |
| case .ascending: |
| print("Ascending") |
| case .descending: |
| print("Descending") |
| case .same: |
| print("Same") |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Enum Cases |
| |
| In general, there is only one `case` per line in an `enum`. The comma-delimited |
| form may be used only when none of the cases have associated values or raw |
| values, all cases fit on a single line, and the cases do not need further |
| documentation because their meanings are obvious from their names. |
| |
| ~~~ swift |
| public enum Token { |
| case comma |
| case semicolon |
| case identifier |
| } |
| |
| public enum Token { |
| case comma, semicolon, identifier |
| } |
| |
| public enum Token { |
| case comma |
| case semicolon |
| case identifier(String) |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| public enum Token { |
| case comma, semicolon, identifier(String) |
| } |
| ~~~ |
| {:.bad} |
| |
| When all cases of an `enum` must be `indirect`, the `enum` itself is declared |
| `indirect` and the keyword is omitted on the individual cases. |
| |
| ~~~ swift |
| public indirect enum DependencyGraphNode { |
| case userDefined(dependencies: [DependencyGraphNode]) |
| case synthesized(dependencies: [DependencyGraphNode]) |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| public enum DependencyGraphNode { |
| indirect case userDefined(dependencies: [DependencyGraphNode]) |
| indirect case synthesized(dependencies: [DependencyGraphNode]) |
| } |
| ~~~ |
| {:.bad} |
| |
| When an `enum` case does not have associated values, empty parentheses are never |
| present. |
| |
| ~~~ swift |
| public enum BinaryTree<Element> { |
| indirect case node(element: Element, left: BinaryTree, right: BinaryTree) |
| case empty // GOOD. |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| public enum BinaryTree<Element> { |
| indirect case node(element: Element, left: BinaryTree, right: BinaryTree) |
| case empty() // AVOID. |
| } |
| ~~~ |
| {:.bad} |
| |
| The cases of an enum must follow a logical ordering that the author could |
| explain if asked. If there is no obviously logical ordering, use a |
| lexicographical ordering based on the cases' names. |
| |
| In the following example, the cases are arranged in numerical order based on the |
| underlying HTTP status code and blank lines are used to separate groups. |
| |
| ~~~ swift |
| public enum HTTPStatus: Int { |
| case ok = 200 |
| |
| case badRequest = 400 |
| case notAuthorized = 401 |
| case paymentRequired = 402 |
| case forbidden = 403 |
| case notFound = 404 |
| |
| case internalServerError = 500 |
| } |
| ~~~ |
| {:.good} |
| |
| The following version of the same enum is less readable. Although the cases are |
| ordered lexicographically, the meaningful groupings of related values has been |
| lost. |
| |
| ~~~ swift |
| public enum HTTPStatus: Int { |
| case badRequest = 400 |
| case forbidden = 403 |
| case internalServerError = 500 |
| case notAuthorized = 401 |
| case notFound = 404 |
| case ok = 200 |
| case paymentRequired = 402 |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Trailing Closures |
| |
| Functions should not be overloaded such that two overloads differ _only_ by the |
| name of their trailing closure argument. Doing so prevents using trailing |
| closure syntax—when the label is not present, a call to the function with |
| a trailing closure is ambiguous. |
| |
| Consider the following example, which prohibits using trailing closure syntax to |
| call `greet`: |
| |
| ~~~ swift |
| func greet(enthusiastically nameProvider: () -> String) { |
| print("Hello, \(nameProvider())! It's a pleasure to see you!") |
| } |
| |
| func greet(apathetically nameProvider: () -> String) { |
| print("Oh, look. It's \(nameProvider()).") |
| } |
| |
| greet { "John" } // error: ambiguous use of 'greet' |
| ~~~ |
| {:.bad} |
| |
| This example is fixed by differentiating some part of the function name other |
| than the closure argument—in this case, the base name: |
| |
| ~~~ swift |
| func greetEnthusiastically(_ nameProvider: () -> String) { |
| print("Hello, \(nameProvider())! It's a pleasure to see you!") |
| } |
| |
| func greetApathetically(_ nameProvider: () -> String) { |
| print("Oh, look. It's \(nameProvider()).") |
| } |
| |
| greetEnthusiastically { "John" } |
| greetApathetically { "not John" } |
| ~~~ |
| {:.good} |
| |
| If a function call has multiple closure arguments, then _none_ are called using |
| trailing closure syntax; _all_ are labeled and nested inside the argument |
| list's parentheses. |
| |
| ~~~ swift |
| UIView.animate( |
| withDuration: 0.5, |
| animations: { |
| // ... |
| }, |
| completion: { finished in |
| // ... |
| }) |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| UIView.animate( |
| withDuration: 0.5, |
| animations: { |
| // ... |
| }) { finished in |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| If a function has a single closure argument and it is the final argument, then |
| it is _always_ called using trailing closure syntax, except in the following |
| cases to resolve ambiguity or parsing errors: |
| |
| 1. As described above, labeled closure arguments must be used to disambiguate |
| between two overloads with otherwise identical arguments lists. |
| 1. Labeled closure arguments must be used in control flow statements where the |
| body of the trailing closure would be parsed as the body of the control flow |
| statement. |
| |
| ~~~ swift |
| Timer.scheduledTimer(timeInterval: 30, repeats: false) { timer in |
| print("Timer done!") |
| } |
| |
| if let firstActive = list.first(where: { $0.isActive }) { |
| process(firstActive) |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| Timer.scheduledTimer(timeInterval: 30, repeats: false, block: { timer in |
| print("Timer done!") |
| }) |
| |
| // This example fails to compile. |
| if let firstActive = list.first { $0.isActive } { |
| process(firstActive) |
| } |
| ~~~ |
| {:.bad} |
| |
| When a function called with trailing closure syntax takes no other arguments, |
| empty parentheses (`()`) after the function name are _never_ present. |
| |
| ~~~ swift |
| let squares = [1, 2, 3].map { $0 * $0 } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let squares = [1, 2, 3].map({ $0 * $0 }) |
| let squares = [1, 2, 3].map() { $0 * $0 } |
| ~~~ |
| {:.bad} |
| |
| ### Trailing Commas |
| |
| Trailing commas in array and dictionary literals are _required_ when each |
| element is placed on its own line. Doing so produces cleaner diffs when items |
| are added to those literals later. |
| |
| ~~~ swift |
| let configurationKeys = [ |
| "bufferSize", |
| "compression", |
| "encoding", // GOOD. |
| ] |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let configurationKeys = [ |
| "bufferSize", |
| "compression", |
| "encoding" // AVOID. |
| ] |
| ~~~ |
| {:.bad} |
| |
| ### Numeric Literals |
| |
| It is recommended but not required that long numeric literals (decimal, |
| hexadecimal, octal, and binary) use the underscore (`_`) separator to group |
| digits for readability when the literal has numeric value or when there exists a |
| domain-specific grouping. |
| |
| Recommended groupings are three digits for decimal (thousands separators), four |
| digits for hexadecimal, four or eight digits for binary literals, or |
| value-specific field boundaries when they exist (such as three digits for octal |
| file permissions). |
| |
| Do not group digits if the literal is an opaque identifier that does not have a |
| meaningful numeric value. |
| |
| ### Attributes |
| |
| Parameterized attributes (such as `@availability(...)` or `@objc(...)`) are each |
| written on their own line immediately before the declaration to which they |
| apply, are lexicographically ordered, and are indented at the same level as the |
| declaration. |
| |
| ~~~ swift |
| @available(iOS 9.0, *) |
| public func coolNewFeature() { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| @available(iOS 9.0, *) public func coolNewFeature() { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| Attributes without parameters (for example, `@objc` without arguments, |
| `@IBOutlet`, or `@NSManaged`) are lexicographically ordered and _may_ be placed |
| on the same line as the declaration if and only if they would fit on that line |
| without requiring the line to be rewrapped. If placing an attribute on the same |
| line as the declaration would require a declaration to be wrapped that |
| previously did not need to be wrapped, then the attribute is placed on its own |
| line. |
| |
| ~~~ swift |
| public class MyViewController: UIViewController { |
| @IBOutlet private var tableView: UITableView! |
| } |
| ~~~ |
| {:.good} |
| |
| |
| ## Naming |
| |
| ### Apple's API Style Guidelines |
| |
| Apple's |
| [official Swift naming and API design guidelines](https://swift.org/documentation/api-design-guidelines/) |
| hosted on swift.org are considered part of this style guide and are followed as |
| if they were repeated here in their entirety. |
| |
| ### Naming Conventions Are Not Access Control |
| |
| Restricted access control (`internal`, `fileprivate`, or `private`) is preferred |
| for the purposes of hiding information from clients, rather than naming |
| conventions. |
| |
| Naming conventions (such as prefixing a leading underscore) are only used in |
| rare situations when a declaration must be given higher visibility than is |
| otherwise desired in order to work around language limitations—for |
| example, a type that has a method that is only intended to be called by other |
| parts of a library implementation that crosses module boundaries and must |
| therefore be declared `public`. |
| |
| ### Identifiers |
| |
| In general, identifiers contain only 7-bit ASCII characters. Unicode identifiers |
| are allowed if they have a clear and legitimate meaning in the problem domain |
| of the code base (for example, Greek letters that represent mathematical |
| concepts) and are well understood by the team who owns the code. |
| |
| ~~~ swift |
| let smile = "😊" |
| let deltaX = newX - previousX |
| let Δx = newX - previousX |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let 😊 = "😊" |
| ~~~ |
| {:.bad} |
| |
| ### Initializers |
| |
| For clarity, initializer arguments that correspond directly to a stored property |
| have the same name as the property. Explicit `self.` is used during assignment |
| to disambiguate them. |
| |
| ~~~ swift |
| public struct Person { |
| public let name: String |
| public let phoneNumber: String |
| |
| // GOOD. |
| public init(name: String, phoneNumber: String) { |
| self.name = name |
| self.phoneNumber = phoneNumber |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| public struct Person { |
| public let name: String |
| public let phoneNumber: String |
| |
| // AVOID. |
| public init(name otherName: String, phoneNumber otherPhoneNumber: String) { |
| name = otherName |
| phoneNumber = otherPhoneNumber |
| } |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Static and Class Properties |
| |
| Static and class properties that return instances of the declaring type are |
| _not_ suffixed with the name of the type. |
| |
| ~~~ swift |
| public class UIColor { |
| public class var red: UIColor { // GOOD. |
| // ... |
| } |
| } |
| |
| public class URLSession { |
| public class var shared: URLSession { // GOOD. |
| // ... |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| public class UIColor { |
| public class var redColor: UIColor { // AVOID. |
| // ... |
| } |
| } |
| |
| public class URLSession { |
| public class var sharedSession: URLSession { // AVOID. |
| // ... |
| } |
| } |
| ~~~ |
| {:.bad} |
| |
| When a static or class property evaluates to a singleton instance of the |
| declaring type, the names `shared` and `default` are commonly used. This style |
| guide does not require specific names for these; the author should choose a name |
| that makes sense for the type. |
| |
| ### Global Constants |
| |
| Like other variables, global constants are `lowerCamelCase`. Hungarian notation, |
| such as a leading `g` or `k`, is not used. |
| |
| ~~~ swift |
| let secondsPerMinute = 60 |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let SecondsPerMinute = 60 |
| let kSecondsPerMinute = 60 |
| let gSecondsPerMinute = 60 |
| let SECONDS_PER_MINUTE = 60 |
| ~~~ |
| {:.bad} |
| |
| ### Delegate Methods |
| |
| Methods on delegate protocols and delegate-like protocols (such as data sources) |
| are named using the linguistic syntax described below, which is inspired by |
| Cocoa's protocols. |
| |
| > The term "delegate's source object" refers to the object that invokes methods |
| > on the delegate. For example, a `UITableView` is the source object that |
| > invokes methods on the `UITableViewDelegate` that is set as the view's |
| > `delegate` property. |
| |
| All methods take the delegate's source object as the first argument. |
| |
| For methods that take the delegate's source object as their **only** argument: |
| |
| * If the method returns `Void` (such as those used to notify the delegate that |
| an event has occurred), then the method's base name is the **delegate's |
| source type** followed by an **indicative verb phrase** describing the |
| event. The argument is **unlabeled.** |
| |
| ~~~ swift |
| func scrollViewDidBeginScrolling(_ scrollView: UIScrollView) |
| ~~~ |
| {:.good} |
| |
| * If the method returns `Bool` (such as those that make an assertion about the |
| delegate's source object itself), then the method's name is the **delegate's |
| source type** followed by an **indicative or conditional verb phrase** |
| describing the assertion. The argument is **unlabeled.** |
| |
| ~~~ swift |
| func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool |
| ~~~ |
| {:.good} |
| |
| * If the method returns some other value (such as those querying for |
| information about a property of the delegate's source object), then the |
| method's base name is a **noun phrase** describing the property being |
| queried. The argument is **labeled with a preposition or phrase with a |
| trailing preposition** that appropriately combines the noun phrase and the |
| delegate's source object. |
| |
| ~~~ swift |
| func numberOfSections(in scrollView: UIScrollView) -> Int |
| ~~~ |
| {:.good} |
| |
| For methods that take **additional** arguments after the delegate's source |
| object, the method's base name is the delegate's source type **by itself** and |
| the first argument is **unlabeled.** Then: |
| |
| * If the method returns `Void`, the second argument is **labeled with an |
| indicative verb phrase** describing the event that has the argument as its |
| **direct object or prepositional object,** and any other arguments (if |
| present) provide further context. |
| |
| ~~~ swift |
| func tableView( |
| _ tableView: UITableView, |
| willDisplayCell cell: UITableViewCell, |
| forRowAt indexPath: IndexPath) |
| ~~~ |
| {:.good} |
| |
| * If the method returns `Bool`, the second argument is **labeled with an |
| indicative or conditional verb phrase** that describes the return value in |
| terms of the argument, and any other arguments (if present) provide further |
| context. |
| |
| ~~~ swift |
| func tableView( |
| _ tableView: UITableView, |
| shouldSpringLoadRowAt indexPath: IndexPath, |
| with context: UISpringLoadedInteractionContext |
| ) -> Bool |
| ~~~ |
| {:.good} |
| |
| * If the method returns some other value, the second argument is **labeled |
| with a noun phrase and trailing preposition** that describes the return |
| value in terms of the argument, and any other arguments (if present) provide |
| further context. |
| |
| ~~~ swift |
| func tableView( |
| _ tableView: UITableView, |
| heightForRowAt indexPath: IndexPath |
| ) -> CGFloat |
| ~~~ |
| {:.good} |
| |
| Apple's documentation on |
| [delegates and data sources](https://developer.apple.com/library/content/documentation/General/Conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html) |
| also contains some good general guidance about such names. |
| |
| ## Programming Practices |
| |
| Common themes among the rules in this section are: avoid redundancy, avoid |
| ambiguity, and prefer implicitness over explicitness unless being explicit |
| improves readability and/or reduces ambiguity. |
| |
| ### Compiler Warnings |
| |
| Code should compile without warnings when feasible. Any warnings that are able |
| to be removed easily by the author must be removed. |
| |
| A reasonable exception is deprecation warnings, where it may not be possible to |
| immediately migrate to the replacement API, or where an API may be deprecated |
| for external users but must still be supported inside a library during a |
| deprecation period. |
| |
| ### Initializers |
| |
| For `struct`s, Swift synthesizes a non-public memberwise `init` that takes |
| arguments for `var` properties and for any `let` properties that lack default |
| values. When that initializer is suitable (that is, a `public` one is not |
| needed), it is used and no explicit initializer is written. |
| |
| The initializers declared by the special `ExpressibleBy*Literal` compiler |
| protocols are never called directly. |
| |
| ~~~ swift |
| struct Kilometers: ExpressibleByIntegerLiteral { |
| init(integerLiteral value: Int) { |
| // ... |
| } |
| } |
| |
| let k1: Kilometers = 10 // GOOD. |
| let k2 = 10 as Kilometers // ALSO GOOD. |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| struct Kilometers: ExpressibleByIntegerLiteral { |
| init(integerLiteral value: Int) { |
| // ... |
| } |
| } |
| |
| let k = Kilometers(integerLiteral: 10) // AVOID. |
| ~~~ |
| {:.bad} |
| |
| Explicitly calling `.init(...)` is allowed only when the receiver of the call is |
| a metatype variable. In direct calls to the initializer using the literal type |
| name, `.init` is omitted. (**Referring** to the initializer directly by using |
| `MyType.init` syntax to convert it to a closure is permitted.) |
| |
| ~~~ swift |
| let x = MyType(arguments) |
| |
| let type = lookupType(context) |
| let x = type.init(arguments) |
| |
| let x = makeValue(factory: MyType.init) |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let x = MyType.init(arguments) |
| ~~~ |
| {:.bad} |
| |
| ### Properties |
| |
| The `get` block for a read-only computed property is omitted and its body is |
| directly nested inside the property declaration. |
| |
| ~~~ swift |
| var totalCost: Int { |
| return items.sum { $0.cost } |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| var totalCost: Int { |
| get { |
| return items.sum { $0.cost } |
| } |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Types with Shorthand Names |
| |
| Arrays, dictionaries, and optional types are written in their shorthand form |
| whenever possible; that is, `[Element]`, `[Key: Value]`, and `Wrapped?`. The |
| long forms `Array<Element>`, `Dictionary<Key, Value>`, and `Optional<Wrapped>` |
| are only written when required by the compiler; for example, the Swift parser |
| requires `Array<Element>.Index` and does not accept `[Element].Index`. |
| |
| ~~~ swift |
| func enumeratedDictionary<Element>( |
| from values: [Element], |
| start: Array<Element>.Index? = nil |
| ) -> [Int: Element] { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| func enumeratedDictionary<Element>( |
| from values: Array<Element>, |
| start: Optional<Array<Element>.Index> = nil |
| ) -> Dictionary<Int, Element> { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| `Void` is a `typealias` for the empty tuple `()`, so from an implementation |
| point of view they are equivalent. In function type declarations (such as |
| closures, or variables holding a function reference), the return type is always |
| written as `Void`, never as `()`. In functions declared with the `func` keyword, |
| the `Void` return type is omitted entirely. |
| |
| Empty argument lists are always written as `()`, never as `Void`. (In fact, |
| the function signature `Void -> Result` is an error in Swift because function |
| arguments must be surrounded by parentheses, and `(Void)` has a different |
| meaning: an argument list with a single empty-tuple argument.) |
| |
| ~~~ swift |
| func doSomething() { |
| // ... |
| } |
| |
| let callback: () -> Void |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| func doSomething() -> Void { |
| // ... |
| } |
| |
| func doSomething2() -> () { |
| // ... |
| } |
| |
| let callback: () -> () |
| ~~~ |
| {:.bad} |
| |
| ### Optional Types |
| |
| Sentinel values are avoided when designing algorithms (for example, an "index" |
| of −1 when an element was not found in a collection). Sentinel values can |
| easily and accidentally propagate through other layers of logic because the type |
| system cannot distinguish between them and valid outcomes. |
| |
| `Optional` is used to convey a non-error result that is either a value or the |
| absence of a value. For example, when searching a collection for a value, not |
| finding the value is still a **valid and expected** outcome, not an error. |
| |
| ~~~ swift |
| func index(of thing: Thing, in things: [Thing]) -> Int? { |
| // ... |
| } |
| |
| if let index = index(of: thing, in: lotsOfThings) { |
| // Found it. |
| } else { |
| // Didn't find it. |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| func index(of thing: Thing, in things: [Thing]) -> Int { |
| // ... |
| } |
| |
| let index = index(of: thing, in: lotsOfThings) |
| if index != -1 { |
| // Found it. |
| } else { |
| // Didn't find it. |
| } |
| ~~~ |
| {:.bad} |
| |
| `Optional` is also used for error scenarios when there is a single, obvious |
| failure state; that is, when an operation may fail for a single domain-specific |
| reason that is clear to the client. (The domain-specific restriction is meant to |
| exclude severe errors that are typically out of the user's control to properly |
| handle, such as out-of-memory errors.) |
| |
| For example, converting a string to an integer would fail if the |
| string does not represent a valid integer that fits into the type's bit width: |
| |
| ~~~ swift |
| struct Int17 { |
| init?(_ string: String) { |
| // ... |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| Conditional statements that test that an `Optional` is non-`nil` but do not |
| access the wrapped value are written as comparisons to `nil`. The following |
| example is clear about the programmer's intent: |
| |
| ~~~ swift |
| if value != nil { |
| print("value was not nil") |
| } |
| ~~~ |
| {:.good} |
| |
| This example, while taking advantage of Swift's pattern matching and binding |
| syntax, obfuscates the intent by appearing to unwrap the value and then |
| immediately throw it away. |
| |
| ~~~ swift |
| if let _ = value { |
| print("value was not nil") |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Error Types |
| |
| Error types are used when there are multiple possible error states. |
| |
| Throwing errors instead of merging them with the return type cleanly separates |
| concerns in the API. Valid inputs and valid state produce valid outputs in the |
| result domain and are handled with standard sequential control flow. Invalid |
| inputs and invalid state are treated as errors and are handled using the |
| relevant syntactic constructs (`do`-`catch` and `try`). For example: |
| |
| ~~~ swift |
| struct Document { |
| enum ReadError: Error { |
| case notFound |
| case permissionDenied |
| case malformedHeader |
| } |
| |
| init(path: String) throws { |
| // ... |
| } |
| } |
| |
| do { |
| let document = try Document(path: "important.data") |
| } catch Document.ReadError.notFound { |
| // ... |
| } catch Document.ReadError.permissionDenied { |
| // ... |
| } catch { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| Such a design forces the caller to consciously acknowledge the failure case by: |
| |
| * wrapping the calling code in a `do`-`catch` block and handling error cases to |
| whichever degree is appropriate, |
| * declaring the function in which the call is made as `throws` and letting the |
| error propagate out, or |
| * using `try?` when the specific reason for failure is unimportant and only the |
| information about whether the call failed is needed. |
| |
| In general, with exceptions noted below, force-`try!` is forbidden; it is |
| equivalent to `try` followed by `fatalError` but without a meaningful message. |
| If an error outcome would mean that the program is in such an unrecoverable |
| state that immediate termination is the only reasonable action, it is better to |
| use `do`-`catch` or `try?` and provide more context in the error message to |
| assist debugging if the operation does fail. |
| |
| > **Exception:** Force-`try!` is allowed in unit tests and test-only code. It is |
| > also allowed in non-test code when it is unmistakably clear that an error |
| > would only be thrown because of **programmer** error; we specifically define |
| > this to mean a single expression that could be evaluated without context in |
| > the Swift REPL. For example, consider initializing a regular expression from a |
| > a string literal: |
| > |
| > ~~~ swift |
| > let regex = try! NSRegularExpression(pattern: "a*b+c?") |
| > ~~~ |
| > {:.good} |
| > |
| > The `NSRegularExpression` initializer throws an error if the regular |
| > expression is malformed, but when it is a string literal, the error would only |
| > occur if the programmer mistyped it. There is no benefit to writing extra |
| > error handling logic here. |
| > |
| > If the pattern above were not a literal but instead were dynamic or derived |
| > from user input, `try!` should **not** be used and errors should be handled |
| > gracefully. |
| |
| ### Force Unwrapping and Force Casts |
| |
| Force-unwrapping and force-casting are often code smells and are strongly |
| discouraged. Unless it is extremely clear from surrounding code why such an |
| operation is safe, a comment should be present that describes the invariant that |
| ensures that the operation is safe. For example, |
| |
| ~~~ swift |
| let value = getSomeInteger() |
| |
| // ...intervening code... |
| |
| // This force-unwrap is safe because `value` is guaranteed to fall within the |
| // valid enum cases because it came from some data source that only permits |
| // those raw values. |
| return SomeEnum(rawValue: value)! |
| ~~~ |
| {:.good} |
| |
| > **Exception:** Force-unwraps are allowed in unit tests and test-only code |
| > without additional documentation. This keeps such code free of unnecessary |
| > control flow. In the event that `nil` is unwrapped or a cast operation is to |
| > an incompatible type, the test will fail which is the desired result. |
| |
| ### Implicitly Unwrapped Optionals |
| |
| Implicitly unwrapped optionals are inherently unsafe and should be avoided |
| whenever possible in favor of non-optional declarations or regular `Optional` |
| types. Exceptions are described below. |
| |
| User-interface objects whose lifetimes are based on the UI lifecycle instead of |
| being strictly based on the lifetime of the owning object are allowed to use |
| implicitly unwrapped optionals. Examples of these include `@IBOutlet` |
| properties connected to objects in a XIB file or storyboard, properties that are |
| initialized externally like in the `prepareForSegue` implementation of a calling |
| view controller, and properties that are initialized elsewhere during a class's |
| life cycle, like views in a view controller's `viewDidLoad` method. Making such |
| properties regular optionals can put too much burden on the user to unwrap them |
| because they are guaranteed to be non-nil and remain that way once the objects |
| are ready for use. |
| |
| ~~~ swift |
| class SomeViewController: UIViewController { |
| @IBOutlet var button: UIButton! |
| |
| override func viewDidLoad() { |
| populateLabel(for: button) |
| } |
| |
| private func populateLabel(for button: UIButton) { |
| // ... |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| Implicitly unwrapped optionals can also surface in Swift code when using |
| Objective-C APIs that lack the appropriate nullability attributes. If possible, |
| coordinate with the owners of that code to add those annotations so that the |
| APIs are imported cleanly into Swift. If this is not possible, try to keep the |
| footprint of those implicitly unwrapped optionals as small as possible in your |
| Swift code; that is, do not propagate them through multiple layers of your own |
| abstractions. |
| |
| Implicitly unwrapped optionals are also allowed in unit tests. This is for |
| reasons similar to the UI object scenario above—the lifetime of test |
| fixtures often begins not in the test's initializer but in the `setUp()` method |
| of a test so that they can be reset before the execution of each test. |
| |
| ### Access Levels |
| |
| Omitting an explicit access level is permitted on declarations. For top-level |
| declarations, the default access level is `internal`. For nested declarations, |
| the default access level is the lesser of `internal` and the access level of the |
| enclosing declaration. |
| |
| Specifying an explicit access level at the file level on an extension is |
| forbidden. Each member of the extension has its access level specified if it is |
| different than the default. |
| |
| ~~~ swift |
| extension String { |
| public var isUppercase: Bool { |
| // ... |
| } |
| |
| public var isLowercase: Bool { |
| // ... |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| public extension String { |
| var isUppercase: Bool { |
| // ... |
| } |
| |
| var isLowercase: Bool { |
| // ... |
| } |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Nesting and Namespacing |
| |
| Swift allows `enum`s, `struct`s, and `class`es to be nested, so nesting is |
| preferred (instead of naming conventions) to express scoped and hierarchical |
| relationships among types when possible. For example, flag `enum`s or error |
| types that are associated with a specific type are nested in that type. |
| |
| ~~~ swift |
| class Parser { |
| enum Error: Swift.Error { |
| case invalidToken(String) |
| case unexpectedEOF |
| } |
| |
| func parse(text: String) throws { |
| // ... |
| } |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| class Parser { |
| func parse(text: String) throws { |
| // ... |
| } |
| } |
| |
| enum ParseError: Error { |
| case invalidToken(String) |
| case unexpectedEOF |
| } |
| ~~~ |
| {:.bad} |
| |
| Swift does not currently allow protocols to be nested in other types or vice |
| versa, so this rule does not apply to situations such as the relationship |
| between a controller class and its delegate protocol. |
| |
| Declaring an `enum` without cases is the canonical way to define a "namespace" |
| to group a set of related declarations, such as constants or helper functions. |
| This `enum` automatically has no instances and does not require that extra |
| boilerplate code be written to prevent instantiation. |
| |
| ~~~ swift |
| enum Dimensions { |
| static let tileMargin: CGFloat = 8 |
| static let tilePadding: CGFloat = 4 |
| static let tileContentSize: CGSize(width: 80, height: 64) |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| struct Dimensions { |
| private init() {} |
| |
| static let tileMargin: CGFloat = 8 |
| static let tilePadding: CGFloat = 4 |
| static let tileContentSize: CGSize(width: 80, height: 64) |
| } |
| ~~~ |
| {:.bad} |
| |
| ### `guard`s for Early Exits |
| |
| A `guard` statement, compared to an `if` statement with an inverted condition, |
| provides visual emphasis that the condition being tested is a special case that |
| causes early exit from the enclosing scope. |
| |
| Furthermore, `guard` statements improve readability by eliminating extra levels |
| of nesting (the "pyramid of doom"); failure conditions are closely coupled to |
| the conditions that trigger them and the main logic remains flush left within |
| its scope. |
| |
| This can be seen in the following examples; in the first, there is a clear |
| progression that checks for invalid states and exits, then executes the main |
| logic in the successful case. In the second example without `guard`, the main |
| logic is buried at an arbitrary nesting level and the thrown errors are |
| separated from their conditions by a great distance. |
| |
| ~~~ swift |
| func discombobulate(_ values: [Int]) throws -> Int { |
| guard let first = values.first else { |
| throw DiscombobulationError.arrayWasEmpty |
| } |
| guard first >= 0 else { |
| throw DiscombobulationError.negativeEnergy |
| } |
| |
| var result = 0 |
| for value in values { |
| result += invertedCombobulatoryFactory(of: value) |
| } |
| return result |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| func discombobulate(_ values: [Int]) throws -> Int { |
| if let first = values.first { |
| if first >= 0 { |
| var result = 0 |
| for value in values { |
| result += invertedCombobulatoryFactor(of: value) |
| } |
| return result |
| } else { |
| throw DiscombobulationError.negativeEnergy |
| } |
| } else { |
| throw DiscombobulationError.arrayWasEmpty |
| } |
| } |
| ~~~ |
| {:.bad} |
| |
| A `guard`-`continue` statement can also be useful in a loop to avoid increased |
| indentation when the entire body of the loop should only be executed in some |
| cases (but see also the `for`-`where` discussion below.) |
| |
| ### `for`-`where` Loops |
| |
| When the entirety of a `for` loop's body would be a single `if` block testing a |
| condition of the element, the test is placed in the `where` clause of the `for` |
| statement instead. |
| |
| ~~~ swift |
| for item in collection where item.hasProperty { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| for item in collection { |
| if item.hasProperty { |
| // ... |
| } |
| } |
| ~~~ |
| {:.bad} |
| |
| ### `fallthrough` in `switch` Statements |
| |
| When multiple `case`s of a `switch` would execute the same statements, the |
| `case` patterns are combined into ranges or comma-delimited lists. Multiple |
| `case` statements that do nothing but `fallthrough` to a `case` below are not |
| allowed. |
| |
| ~~~ swift |
| switch value { |
| case 1: print("one") |
| case 2...4: print("two to four") |
| case 5, 7: print("five or seven") |
| default: break |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| switch value { |
| case 1: print("one") |
| case 2: fallthrough |
| case 3: fallthrough |
| case 4: print("two to four") |
| case 5: fallthrough |
| case 7: print("five or seven") |
| default: break |
| } |
| ~~~ |
| {:.bad} |
| |
| In other words, there is never a `case` whose body contains _only_ the |
| `fallthrough` statement. Cases containing _additional_ statements which then |
| fallthrough to the next case are permitted. |
| |
| ### Pattern Matching |
| |
| The `let` and `var` keywords are placed individually in front of _each_ element |
| in a pattern that is being matched. The shorthand version of `let`/`var` that |
| precedes and distributes across the entire pattern is forbidden because it can |
| introduce unexpected behavior if a value being matched in a pattern is itself a |
| variable. |
| |
| ~~~ swift |
| enum DataPoint { |
| case unlabeled(Int) |
| case labeled(String, Int) |
| } |
| |
| let label = "goodbye" |
| |
| // `label` is treated as a value here because it is not preceded by `let`, so |
| // the pattern below matches only data points that have the label "goodbye". |
| switch DataPoint.labeled("hello", 100) { |
| case .labeled(label, let value): |
| // ... |
| } |
| |
| // Writing `let` before each individual binding clarifies that the intent is to |
| // introduce a new binding (shadowing the local variable within the case) rather |
| // than to match against the value of the local variable. Thus, this pattern |
| // matches data points with any string label. |
| switch DataPoint.labeled("hello", 100) { |
| case .labeled(let label, let value): |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| In the example below, if the author's intention was to match using the value of |
| the `label` variable above, that has been lost because `let` distributes across |
| the entire pattern and thus shadows the variable with a binding that applies to |
| any string value: |
| |
| ~~~ swift |
| switch DataPoint.labeled("hello", 100) { |
| case let .labeled(label, value): |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| Labels of tuple arguments and `enum` associated values are omitted when binding |
| a value to a variable with the same name as the label. |
| |
| ~~~ swift |
| enum BinaryTree<Element> { |
| indirect case subtree(left: BinaryTree<Element>, right: BinaryTree<Element>) |
| case leaf(element: Element) |
| } |
| |
| switch treeNode { |
| case .subtree(let left, let right): |
| // ... |
| case .leaf(let element): |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| Including the labels adds noise that is redundant and lacking useful |
| information: |
| |
| ~~~ swift |
| switch treeNode { |
| case .subtree(left: let left, right: let right): |
| // ... |
| case .leaf(element: let element): |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Tuple Patterns |
| |
| Assigning variables through a tuple pattern (sometimes referred to as a _tuple |
| shuffle_) is only permitted if the left-hand side of the assignment is |
| unlabeled. |
| |
| ~~~ swift |
| let (a, b) = (y: 4, x: 5.0) |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let (x: a, y: b) = (y: 4, x: 5.0) |
| ~~~ |
| {:.bad} |
| |
| Labels on the left-hand side closely resemble type annotations, and can lead to |
| confusing code. |
| |
| ~~~ swift |
| // This declares two variables, `Int`, which is a `Double` with value 5.0, and |
| // `Double`, which is an `Int` with value 4. |
| // `x` and `y` are not variables. |
| let (x: Int, y: Double) = (y: 4, x: 5.0) |
| ~~~ |
| {:.bad} |
| |
| ### Numeric and String Literals |
| |
| Integer and string literals in Swift do not have an intrinsic type. For example, |
| `5` by itself is not an `Int`; it is a special literal value that can express |
| any type that conforms to `ExpressibleByIntegerLiteral` and only becomes an |
| `Int` if type inference does not map it to a more specific type. Likewise, the |
| literal `"x"` is neither `String` nor `Character` nor `UnicodeScalar`, but it |
| can become any of those types depending on its context, falling back to `String` |
| as a default. |
| |
| Thus, when a literal is used to initialize a value of a type other than its |
| default, and when that type cannot be inferred otherwise by context, specify the |
| type explicitly in the declaration or use an `as` expression to coerce it. |
| |
| ~~~ swift |
| // Without a more explicit type, x1 will be inferred as type Int. |
| let x1 = 50 |
| |
| // These are explicitly type Int32. |
| let x2: Int32 = 50 |
| let x3 = 50 as Int32 |
| |
| // Without a more explicit type, y1 will be inferred as type String. |
| let y1 = "a" |
| |
| // These are explicitly type Character. |
| let y2: Character = "a" |
| let y3 = "a" as Character |
| |
| // These are explicitly type UnicodeScalar. |
| let y4: UnicodeScalar = "a" |
| let y5 = "a" as UnicodeScalar |
| |
| func writeByte(_ byte: UInt8) { |
| // ... |
| } |
| // Inference also occurs for function arguments, so 50 is a UInt8 without |
| // explicitly coercion. |
| writeByte(50) |
| ~~~ |
| {:.good} |
| |
| The compiler will emit errors appropriately for invalid literal coercions if, |
| for example, a number does not fit into the integer type or a multi-character |
| string is coerced to a character. So while the following examples emit errors, |
| they are "good" because the errors are caught at compile-time and for the right |
| reasons. |
| |
| ~~~ swift |
| // error: integer literal '9223372036854775808' overflows when stored into 'Int64' |
| let a = 0x8000_0000_0000_0000 as Int64 |
| |
| // error: cannot convert value of type 'String' to type 'Character' in coercion |
| let b = "ab" as Character |
| ~~~ |
| {:.good} |
| |
| Using initializer syntax for these types of coercions can lead to misleading |
| compiler errors, or worse, hard-to-debug runtime errors. |
| |
| ~~~ swift |
| // This first tries to create an `Int` (signed) from the literal and then |
| // convert it to a `UInt64`. Even though this literal fits into a `UInt64`, it |
| // doesn't fit into an `Int` first, so it doesn't compile. |
| let a1 = UInt64(0x8000_0000_0000_0000) |
| |
| // This invokes `Character.init(_: String)`, thus creating a `String` "a" at |
| // runtime (which involves a slow heap allocation), extracting the character |
| // from it, and then releasing it. This is significantly slower than a proper |
| // coercion. |
| let b = Character("a") |
| |
| // As above, this creates a `String` and then `Character.init(_: String)` |
| // attempts to extract the single character from it. This fails a precondition |
| // check and traps at runtime. |
| let c = Character("ab") |
| ~~~ |
| {:.bad} |
| |
| ### Playground Literals |
| |
| The graphically-rendered playground literals `#colorLiteral(...)`, |
| `#imageLiteral(...)`, and `#fileLiteral(...)` are forbidden in non-playground |
| production code. They are permitted in playground sources. |
| |
| ~~~ swift |
| let color = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| let color = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) |
| ~~~ |
| {:.bad} |
| |
| ### Trapping vs. Overflowing Arithmetic |
| |
| The standard (trapping-on-overflow) arithmetic and bitwise operators (`+`, `-`, |
| `*`, `<<`, and `>>`) are used for most normal operations, rather than the |
| masking operations (preceded by `&`). Trapping on overflow is safer because it |
| prevents bad data from propagating through other layers of the system. |
| |
| ~~~ swift |
| // GOOD. Overflow will not cause the balance to go negative. |
| let newBankBalance = oldBankBalance + recentHugeProfit |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| // AVOID. Overflow will cause the balance to go negative if the summands are |
| // large. |
| let newBankBalance = oldBankBalance &+ recentHugeProfit |
| ~~~ |
| {:.bad} |
| |
| Masking operations are comparatively rare but are permitted (and in fact |
| necessary for correctness) in problem domains that use modular arithmetic, such |
| as cryptography, big-integer implementations, hash functions, and so forth. |
| |
| ~~~ swift |
| var hashValue: Int { |
| // GOOD. What matters here is the distribution of the bit pattern rather than |
| // the actual numeric value. |
| return foo.hashValue &+ 31 * (bar.hashValue &+ 31 &* baz.hashValue) |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| var hashValue: Int { |
| // INCORRECT. This will trap arbitrarily and unpredictably depending on the |
| // hash values of the individual terms. |
| return foo.hashValue + 31 * (bar.hashValue + 31 * baz.hashValue) |
| } |
| ~~~ |
| {:.bad} |
| |
| Masking operations are also permitted in performance-sensitive code where the |
| values are already known to not cause overflow (or where overflow is not a |
| concern). In this case, comments should be used to indicate why the use of |
| masking operations is important. Additionally, consider adding debug |
| preconditions to check these assumptions without affecting performance of |
| optimized builds. |
| |
| ### Defining New Operators |
| |
| When used unwisely, custom-defined operators can significantly reduce the |
| readability of code because such operators often lack the historical context of |
| the more common ones built into the standard library. |
| |
| In general, defining custom operators should be avoided. However, it is allowed |
| when an operator has a clear and well-defined meaning in the problem domain |
| and when using an operator significantly improves the readability of the code |
| when compared to function calls. For example, since `*` is the only |
| multiplication operator defined by Swift (not including the masking version), a |
| numeric matrix library may define additional operators to support other |
| operations like cross product and dot product. |
| |
| An example of a prohibited use case is defining custom `<~~` and `~~>` operators |
| to decode and encode JSON data. Such operators are not native to the problem |
| domain of processing JSON and even an experienced Swift engineer would have |
| difficulty understanding the purpose of the code without seeking out |
| documentation of those operators. |
| |
| If you must use third-party code of unquestionable value that provides an API |
| only available through custom operators, you are **strongly encouraged** to |
| consider writing a wrapper that defines more readable methods that delegate to |
| the custom operators. This will significantly reduce the learning curve required |
| to understand how such code works for new teammates and other code reviewers. |
| |
| ### Overloading Existing Operators |
| |
| Overloading operators is permitted when your use of the operator is semantically |
| equivalent to the existing uses in the standard library. Examples of permitted |
| use cases are implementing the operator requirements for `Equatable` and |
| `Hashable`, or defining a new `Matrix` type that supports arithmetic operations. |
| |
| If you wish to overload an existing operator with a meaning other than its |
| natural meaning, follow the guidance in |
| [Defining New Operators](#defining-new-operators) to determine whether this is |
| permitted. In other words, if the new meaning is well-established in the problem |
| domain and the use of the operator is a readability improvement over other |
| syntactic constructs, then it is permitted. |
| |
| An example of a prohibited case of operator repurposing would be to overload `*` |
| and `+` to build an ad hoc regular expression API. Such an API would not provide |
| strong enough readability benefits compared to simply representing the entire |
| regular expression as a string. |
| |
| ## Documentation Comments |
| |
| ### General Format |
| |
| Documentation comments are written using the format where each line is preceded |
| by a triple slash (`///`). Javadoc-style block comments (`/** ... */`) are not |
| permitted. |
| |
| ~~~ swift |
| /// Returns the numeric value of the given digit represented as a Unicode scalar. |
| /// |
| /// - Parameters: |
| /// - digit: The Unicode scalar whose numeric value should be returned. |
| /// - radix: The radix, between 2 and 36, used to compute the numeric value. |
| /// - Returns: The numeric value of the scalar. |
| func numericValue(of digit: UnicodeScalar, radix: Int = 10) -> Int { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| /** |
| * Returns the numeric value of the given digit represented as a Unicode scalar. |
| * |
| * - Parameters: |
| * - digit: The Unicode scalar whose numeric value should be returned. |
| * - radix: The radix, between 2 and 36, used to compute the numeric value. |
| * - Returns: The numeric value of the scalar. |
| */ |
| func numericValue(of digit: UnicodeScalar, radix: Int = 10) -> Int { |
| // ... |
| } |
| |
| /** |
| Returns the numeric value of the given digit represented as a Unicode scalar. |
| |
| - Parameters: |
| - digit: The Unicode scalar whose numeric value should be returned. |
| - radix: The radix, between 2 and 36, used to compute the numeric value. |
| - Returns: The numeric value of the scalar. |
| */ |
| func numericValue(of digit: UnicodeScalar, radix: Int = 10) -> Int { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Single-Sentence Summary |
| |
| Documentation comments begin with a brief **single-sentence** summary that |
| describes the declaration. (This sentence may span multiple lines, but if it |
| spans too many lines, the author should consider whether the summary can be |
| simplified and details moved to a new paragraph.) |
| |
| If more detail is needed than can be stated in the summary, additional |
| paragraphs (each separated by a blank line) are added after it. |
| |
| The single-sentence summary is not necessarily a complete sentence; for example, |
| method summaries are generally written as verb phrases **without** "this method |
| [...]" because it is already implied as the subject and writing it out would be |
| redundant. Likewise, properties are often written as noun phrases **without** |
| "this property is [...]". In any case, however, they are still terminated with a |
| period. |
| |
| ~~~ swift |
| /// The background color of the view. |
| var backgroundColor: UIColor |
| |
| /// Returns the sum of the numbers in the given array. |
| /// |
| /// - Parameter numbers: The numbers to sum. |
| /// - Returns: The sum of the numbers. |
| func sum(_ numbers: [Int]) -> Int { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| ~~~ swift |
| /// This property is the background color of the view. |
| var backgroundColor: UIColor |
| |
| /// This method returns the sum of the numbers in the given array. |
| /// |
| /// - Parameter numbers: The numbers to sum. |
| /// - Returns: The sum of the numbers. |
| func sum(_ numbers: [Int]) -> Int { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Parameter, Returns, and Throws Tags |
| |
| Clearly document the parameters, return value, and thrown errors of functions |
| using the `Parameter(s)`, `Returns`, and `Throws` tags, in that order. None ever |
| appears with an empty description. When a description does not fit on a single |
| line, continuation lines are indented 2 spaces in from the position of the |
| hyphen starting the tag. |
| |
| The recommended way to write documentation comments in Xcode is to place the |
| text cursor on the declaration and press **Command + Option + /**. This will |
| automatically generate the correct format with placeholders to be filled in. |
| |
| `Parameter(s)` and `Returns` tags may be omitted only if the single-sentence |
| brief summary fully describes the meaning of those items and including the tags |
| would only repeat what has already been said. |
| |
| The content following the `Parameter(s)`, `Returns`, and `Throws` tags should be |
| terminated with a period, even when they are phrases instead of complete |
| sentences. |
| |
| When a method takes a single argument, the singular inline form of the |
| `Parameter` tag is used. When a method takes multiple arguments, the grouped |
| plural form `Parameters` is used and each argument is written as an item in a |
| nested list with only its name as the tag. |
| |
| ~~~ swift |
| /// Returns the output generated by executing a command. |
| /// |
| /// - Parameter command: The command to execute in the shell environment. |
| /// - Returns: A string containing the contents of the invoked process's |
| /// standard output. |
| func execute(command: String) -> String { |
| // ... |
| } |
| |
| /// Returns the output generated by executing a command with the given string |
| /// used as standard input. |
| /// |
| /// - Parameters: |
| /// - command: The command to execute in the shell environment. |
| /// - stdin: The string to use as standard input. |
| /// - Returns: A string containing the contents of the invoked process's |
| /// standard output. |
| func execute(command: String, stdin: String) -> String { |
| // ... |
| } |
| ~~~ |
| {:.good} |
| |
| The following examples are incorrect, because they use the plural form of |
| `Parameters` for a single parameter or the singular form `Parameter` for |
| multiple parameters. |
| |
| ~~~ swift |
| /// Returns the output generated by executing a command. |
| /// |
| /// - Parameters: |
| /// - command: The command to execute in the shell environment. |
| /// - Returns: A string containing the contents of the invoked process's |
| /// standard output. |
| func execute(command: String) -> String { |
| // ... |
| } |
| |
| /// Returns the output generated by executing a command with the given string |
| /// used as standard input. |
| /// |
| /// - Parameter command: The command to execute in the shell environment. |
| /// - Parameter stdin: The string to use as standard input. |
| /// - Returns: A string containing the contents of the invoked process's |
| /// standard output. |
| func execute(command: String, stdin: String) -> String { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| ### Apple's Markup Format |
| |
| Use of |
| [Apple's markup format](https://developer.apple.com/library/content/documentation/Xcode/Reference/xcode_markup_formatting_ref/) |
| is strongly encouraged to add rich formatting to documentation. Such markup |
| helps to differentiate symbolic references (like parameter names) from |
| descriptive text in comments and is rendered by Xcode and other documentation |
| generation tools. Some examples of frequently used directives are listed below. |
| |
| * Paragraphs are separated using a single line that starts with `///` and is |
| otherwise blank. |
| * *\*Single asterisks\** and _\_single underscores\__ surround text that should |
| be rendered in italic/oblique type. |
| * **\*\*Double asterisks\*\*** and __\_\_double underscores\_\___ surround text |
| that should be rendered in boldface. |
| * Names of symbols or inline code are surrounded in `` `backticks` ``. |
| * Multi-line code (such as example usage) is denoted by placing three backticks |
| (` ``` `) on the lines before and after the code block. |
| |
| ### Where to Document |
| |
| At a minimum, documentation comments are present for every open or public |
| declaration, and every open or public member of such a declaration, with |
| specific exceptions noted below: |
| |
| * Individual cases of an `enum` often are not documented if their meaning is |
| self-explanatory from their name. Cases with associated values, however, |
| should document what those values mean if it is not obvious. |
| |
| * A documentation comment is not always present on a declaration that overrides |
| a supertype declaration or implements a protocol requirement, or on a |
| declaration that provides the default implementation of a protocol requirement |
| in an extension. |
| |
| It is acceptable to document an overridden declaration to describe new |
| behavior from the declaration that it overrides. In no case should the |
| documentation for the override be a mere copy of the base declaration's |
| documentation. |
| |
| * A documentation comment is not always present on test classes and test |
| methods. However, they can be useful for functional test classes and for |
| helper classes/methods shared by multiple tests. |
| |
| * A documentation comment is not always present on an extension declaration |
| (that is, the `extension` itself). You may choose to add one if it help |
| clarify the purpose of the extension, but avoid meaningless or misleading |
| comments. |
| |
| In the following example, the comment is just repetition of what is already |
| obvious from the source code: |
| |
| ~~~ swift |
| /// Add `Equatable` conformance. |
| extension MyType: Equatable { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| The next example is more subtle, but it is an example of documentation that is |
| not scalable because the extension or the conformance could be updated in the |
| future. Consider that the type may be made `Comparable` at the time of that |
| writing in order to sort the values, but that is not the only possible use of |
| that conformance and client code could use it for other purposes in the |
| future. |
| |
| ~~~ swift |
| /// Make `Candidate` comparable so that they can be sorted. |
| extension Candidate: Comparable { |
| // ... |
| } |
| ~~~ |
| {:.bad} |
| |
| In general, if you find yourself writing documentation that simply repeats |
| information that is obvious from the source and sugaring it with words like |
| "a representation of," then leave the comment out entirely. |
| |
| However, it is _not_ appropriate to cite this exception to justify omitting |
| relevant information that a typical reader might need to know. For example, for |
| a property named `canonicalName`, don't omit its documentation (with the |
| rationale that it would only say `/// The canonical name.`) if a typical reader |
| may have no idea what the term "canonical name" means in that context. Use the |
| documentation as an opportunity to define the term. |