Style guide & coding conventions for Swift projects

Overview

This repository is no longer active.


A guide to our Swift style and conventions.

This is an attempt to encourage patterns that accomplish the following goals (in rough priority order):

  1. Increased rigor, and decreased likelihood of programmer error
  2. Increased clarity of intent
  3. Reduced verbosity
  4. Fewer debates about aesthetics

If you have suggestions, please see our contribution guidelines, then open a pull request.


Whitespace

  • Tabs, not spaces.
  • End files with a newline.
  • Make liberal use of vertical whitespace to divide code into logical chunks.
  • Don’t leave trailing whitespace.
    • Not even leading indentation on blank lines.

Prefer let-bindings over var-bindings wherever possible

Use let foo = … over var foo = … wherever possible (and when in doubt). Only use var if you absolutely have to (i.e. you know that the value might change, e.g. when using the weak storage modifier).

Rationale: The intent and meaning of both keywords are clear, but let-by-default results in safer and clearer code.

A let-binding guarantees and clearly signals to the programmer that its value will never change. Subsequent code can thus make stronger assumptions about its usage.

It becomes easier to reason about code. Had you used var while still making the assumption that the value never changed, you would have to manually check that.

Accordingly, whenever you see a var identifier being used, assume that it will change and ask yourself why.

Return and break early

When you have to meet certain criteria to continue execution, try to exit early. So, instead of this:

if n.isNumber {
    // Use n here
} else {
    return
}

use this:

guard n.isNumber else {
    return
}
// Use n here

You can also do it with if statement, but using guard is preferred, because guard statement without return, break or continue produces a compile-time error, so exit is guaranteed.

Avoid Using Force-Unwrapping of Optionals

If you have an identifier foo of type FooType? or FooType!, don't force-unwrap it to get to the underlying value (foo!) if possible.

Instead, prefer this:

if let foo = foo {
    // Use unwrapped `foo` value in here
} else {
    // If appropriate, handle the case where the optional is nil
}

Alternatively, you might want to use Swift's Optional Chaining in some of these cases, such as:

// Call the function if `foo` is not nil. If `foo` is nil, ignore we ever tried to make the call
foo?.callSomethingIfFooIsNotNil()

Rationale: Explicit if let-binding of optionals results in safer code. Force unwrapping is more prone to lead to runtime crashes.

Avoid Using Implicitly Unwrapped Optionals

Where possible, use let foo: FooType? instead of let foo: FooType! if foo may be nil (Note that in general, ? can be used instead of !).

Rationale: Explicit optionals result in safer code. Implicitly unwrapped optionals have the potential of crashing at runtime.

Prefer implicit getters on read-only properties and subscripts

When possible, omit the get keyword on read-only computed properties and read-only subscripts.

So, write these:

var myGreatProperty: Int {
	return 4
}

subscript(index: Int) -> T {
    return objects[index]
}

… not these:

var myGreatProperty: Int {
	get {
		return 4
	}
}

subscript(index: Int) -> T {
    get {
        return objects[index]
    }
}

Rationale: The intent and meaning of the first version are clear, and results in less code.

Always specify access control explicitly for top-level definitions

Top-level functions, types, and variables should always have explicit access control specifiers:

public var whoopsGlobalState: Int
internal struct TheFez {}
private func doTheThings(things: [Thing]) {}

However, definitions within those can leave access control implicit, where appropriate:

internal struct TheFez {
	var owner: Person = Joshaber()
}

Rationale: It's rarely appropriate for top-level definitions to be specifically internal, and being explicit ensures that careful thought goes into that decision. Within a definition, reusing the same access control specifier is just duplicative, and the default is usually reasonable.

When specifying a type, always associate the colon with the identifier

When specifying the type of an identifier, always put the colon immediately after the identifier, followed by a space and then the type name.

class SmallBatchSustainableFairtrade: Coffee { ... }

let timeToCoffee: NSTimeInterval = 2

func makeCoffee(type: CoffeeType) -> Coffee { ... }

Rationale: The type specifier is saying something about the identifier so it should be positioned with it.

Also, when specifying the type of a dictionary, always put the colon immediately after the key type, followed by a space and then the value type.

let capitals: [Country: City] = [sweden: stockholm]

Only explicitly refer to self when required

When accessing properties or methods on self, leave the reference to self implicit by default:

private class History {
	var events: [Event]

	func rewrite() {
		events = []
	}
}

Only include the explicit keyword when required by the language—for example, in a closure, or when parameter names conflict:

extension History {
	init(events: [Event]) {
		self.events = events
	}

	var whenVictorious: () -> () {
		return {
			self.rewrite()
		}
	}
}

Rationale: This makes the capturing semantics of self stand out more in closures, and avoids verbosity elsewhere.

Prefer structs over classes

Unless you require functionality that can only be provided by a class (like identity or deinitializers), implement a struct instead.

Note that inheritance is (by itself) usually not a good reason to use classes, because polymorphism can be provided by protocols, and implementation reuse can be provided through composition.

For example, this class hierarchy:

class Vehicle {
    let numberOfWheels: Int

    init(numberOfWheels: Int) {
        self.numberOfWheels = numberOfWheels
    }

    func maximumTotalTirePressure(pressurePerWheel: Float) -> Float {
        return pressurePerWheel * Float(numberOfWheels)
    }
}

class Bicycle: Vehicle {
    init() {
        super.init(numberOfWheels: 2)
    }
}

class Car: Vehicle {
    init() {
        super.init(numberOfWheels: 4)
    }
}

could be refactored into these definitions:

protocol Vehicle {
    var numberOfWheels: Int { get }
}

func maximumTotalTirePressure(vehicle: Vehicle, pressurePerWheel: Float) -> Float {
    return pressurePerWheel * Float(vehicle.numberOfWheels)
}

struct Bicycle: Vehicle {
    let numberOfWheels = 2
}

struct Car: Vehicle {
    let numberOfWheels = 4
}

Rationale: Value types are simpler, easier to reason about, and behave as expected with the let keyword.

Make classes final by default

Classes should start as final, and only be changed to allow subclassing if a valid need for inheritance has been identified. Even in that case, as many definitions as possible within the class should be final as well, following the same rules.

Rationale: Composition is usually preferable to inheritance, and opting in to inheritance hopefully means that more thought will be put into the decision.

Omit type parameters where possible

Methods of parameterized types can omit type parameters on the receiving type when they’re identical to the receiver’s. For example:

struct Composite<T> {
	
	func compose(other: Composite
   ) 
   -> Composite
   
     {
		
    return Composite
    <T
    >(
    self, other)
	}
}
   
  

could be rendered as:

struct Composite<T> {
	
	func compose(other: Composite) -> Composite {
		return Composite(self, other)
	}
}

Rationale: Omitting redundant type parameters clarifies the intent, and makes it obvious by contrast when the returned type takes different type parameters.

Use whitespace around operator definitions

Use whitespace around operators when defining them. Instead of:

func <|(lhs: Int, rhs: Int) -> Int
func <|<<A>(lhs: A, rhs: A) -> A

write:

func <| (lhs: Int, rhs: Int) -> Int
func <|< <A>(lhs: A, rhs: A) -> A

Rationale: Operators consist of punctuation characters, which can make them difficult to read when immediately followed by the punctuation for a type or value parameter list. Adding whitespace separates the two more clearly.

Translations

Comments
  • Amend CONTRIBUTING.md to note the document’s purpose

    Amend CONTRIBUTING.md to note the document’s purpose

    We’ve described this document’s purpose as being descriptive rather than prescriptive in issue comments, but I noticed it’s not mentioned in CONTRIBUTING.md. This PR aims to amend that.

    opened by robrix 7
  • Propose not using force-unwrapping of optionals.

    Propose not using force-unwrapping of optionals.

    Pretty straightforward.

    Force-unwrapping of optionals (either implicit or explicit) carries with it the risk of runtime crashes, which should be strongly avoided. There is hardly a reason to ever force-unwrap, and unless you really know what you're doing (and even then) it may go bad.

    I personally try not to have a single exclamation mark in my code.

    opened by dennda 7
  • Propose by-default usage of `let` over `var`.

    Propose by-default usage of `let` over `var`.

    The intent and meaning of both keywords is clear, but let-by-default results in safer and clearer code.

    This is simple, subtle, but IMHO important. I wasn't sure how much code sample you wanted for such a small thing, so I kept it pretty basic. If you choose to merge, feel free to edit and/or change the formatting.

    opened by dennda 7
  • Add guideline to avoid parens in conditionals

    Add guideline to avoid parens in conditionals

    This is yet another area where Swift states that something is 'not required.' While this flexibility can be powerful, it can also lead to inconsistent code - especially on larger teams. Our team tries to adhere to the general principle of always writing the least amount of code possible and this guideline supports that.

    opened by thomasjeans 6
  • Change let to var in section on implicitly unwrapped optionals.

    Change let to var in section on implicitly unwrapped optionals.

    Since let declares a constant, there is no good reason to declare a let variable as an optional type. That variable would always be nil or always be non-nil.

    opened by jamieforrest 6
  • Tweaking spacing rule, please discuss

    Tweaking spacing rule, please discuss

    What's far more important than enforcing one spacing rule over another (tabs or spaces) is that the whole file is consistent in its spacing, not that one religiously enforces a particular variety.

    This is my explanation and rationale. Code samples should be self-explanitory and wouldn't add anything at all (whitespace are notoriously difficult to compare on screen).

    EDIT: Should also note that this speaks directly to Goal number 4.

    opened by jeremytregunna 5
  • Translated to Japanese

    Translated to Japanese

    Hi!

    I'm one of Japannese Swifter.

    About 20 days ago, I translated your awesome swift-style-guide to Japanese. Then, many Japanese read my translation!

    So, I want to add it to master repository not mine because I want new swifters to read this awesome guide.

    If this PR doesn't fit for you, I'm sorry about that. Thanks!

    opened by jarinosuke 4
  • implicit type information

    implicit type information

    Was just reviewing a co-worker's PR and wanted to point them at this document as an explanation for why not to use redundant type declarations, but it wasn't in here. I thought it was?

    Anyway: I think there's still a lot of ambiguity in terms of declaring vars in swift, e.g. whether we prefer var anArray: [Int] = [] or var anArray = [Int](). I prefer the latter, but it feels mostly aesthetic.

    So this is really concerned with actual redundancy. Let me know if there's anything I can do to make this clearer.

    opened by cmyr 4
  • Propose using optional form of as-casts only.

    Propose using optional form of as-casts only.

    IMHO you should be needing as casts very rarely (if ever). as?-casts provide a safer alternative.

    One notable exception might be to access bridged functionality. I.e. if you have a myString: String and you want to call -length (or whatever), then you should be doing (myString as NSString).length() to access the bridged functionality.

    I'm all for proposing typing a few characters more if it means safer code and fewer runtime crashes.

    opened by dennda 4
  • Propose never using implicitly unwrapped optionals.

    Propose never using implicitly unwrapped optionals.

    This should be straightforward.

    Implicitly unwrapped optionals are bad. IMHO they shouldn't exist in the language and are only a stopgap solution used by Apple while they migrate all AppKit/UIKit signatures over to explicit optionals (or no optionals).

    I am not sure if this needs further explanation…?

    The only place I have ever found implicitly unwrapped optionals to be somewhat OK is in conjunction with IBOutlets, but I don't know if that should be mentioned here. Thoughts?

    opened by dennda 4
  • Use a protocol extension instead of a free function in

    Use a protocol extension instead of a free function in "Prefer structs over classes"

    In the "Prefer structs over classes" section, the refactored implementation includes a free function, maximumTotalTirePressure(vehicle:pressurePerWheel:), to replace the functionality that had been provided by a method on the superclass.

    However, an alternative way of implementing this is to include maximumTotalTirePressure(pressurePerWheel:) as a requirement of the Vehicle protocol, and then provide a default implementation through a protocol extension. Using this design, calling the code is less verbose, as the function has fewer arguments. The end result is also more similar to the implementation that used classes, in that the method is called like so:

    let bicycle = Bicycle()
    bicycle.maximumTotalTirePressure(pressurePerWheel: 90)
    
    let car = Car()
    car.maximumTotalTirePressure(pressurePerWheel: 31)
    

    ...instead of being called like this:

    let bicycle = Bicycle()
    maximumTotalTirePressure(vehicle: bicycle: pressurePerWheel: 90)
    
    let car = Car()
    maximumTotalTirePressure(vehicle: car, pressurePerWheel: 31)
    

    The intent of this code is clearer, because the method requirement on the protocol clearly states that every type conforming to Vehicle implements this method, instead of forcing someone who is reading the code to search for the free function that implements this functionality. In addition, types could provide their own implementation if needed.

    opened by nerosnm 3
Owner
GitHub
How people build software.
GitHub
A style guide that outlines the coding conventions for raywenderlich.com

The official raywenderlich.com Objective-C style guide. This style guide outlines the coding conventions for raywenderlich.com. Introduction The reaso

raywenderlich 3.1k Jan 2, 2023
The official Swift style guide for raywenderlich.com.

The Official raywenderlich.com Swift Style Guide. Updated for Swift 5 This style guide is different from others you may see, because the focus is cent

raywenderlich 12.5k Dec 30, 2022
A style guide for Swift.

Table Of Contents Overview Linter Standards Naming Conventions File Structure Types Statement Termination Variable Declaration Self Structs & Classes

Prolific Interactive 171 Oct 4, 2022
LinkedIn's Official Swift Style Guide

Swift Style Guide Make sure to read Apple's API Design Guidelines. Specifics from these guidelines + additional remarks are mentioned below. This guid

LinkedIn 1.4k Dec 13, 2022
The Objective-C Style Guide used by The New York Times

NYTimes Objective-C Style Guide This style guide outlines the coding conventions of the iOS teams at The New York Times. We welcome your feedback in i

The New York Times 5.8k Jan 6, 2023
A CSS-like style library for SwiftUI.

The missing CSS-like module for SwiftUI

hite 112 Dec 23, 2022
👕👚 Theme management in Swift

Themes Story Ever want to support Night mode? Or skin the app differently depending on the seasons? Or toggle features according to paid status? Well,

Khoa 238 Dec 26, 2022
A starter project for Sample Project in swift 5, Xcode 12.5

A starter project for Sample Project in swift 5, Xcode 12.5 (also bridging header included so you could use objective c code in it as well ).

Zeeshan Haider 51 Oct 27, 2022
Declarative view styling in Swift. Inspired by CSS modules.

Gaikan gives you powerful styling capabilities using a declarative DSL in Swift. Inspired by React: CSS in JS and CSS modules. To style UIView(s) just

null 141 Aug 23, 2021
Theme handling macOS Appkit (Swift/Objective-C)

DSFAppearanceManager A class for simplifying macOS appearance values and detecting setting changes (Swift/Objective-C). Why? If you're performing cust

Darren Ford 8 Nov 1, 2022
Style guide & coding conventions for Objective-C projects

This repository is no longer active. These guidelines build on Apple's existing Coding Guidelines for Cocoa. Unless explicitly contradicted below, ass

GitHub 1.7k Dec 9, 2022
A style guide that outlines the coding conventions for raywenderlich.com

The official raywenderlich.com Objective-C style guide. This style guide outlines the coding conventions for raywenderlich.com. Introduction The reaso

raywenderlich 3.1k Jan 2, 2023
SwiftLint - A tool to enforce Swift style and conventions, loosely based on Swift Style Guide.

SwiftLint - A tool to enforce Swift style and conventions, loosely based on Swift Style Guide.

Realm 16.9k Dec 30, 2022
A tool to enforce Swift style and conventions.

SwiftLint A tool to enforce Swift style and conventions, loosely based on the now archived GitHub Swift Style Guide. SwiftLint enforces the style guid

Realm 16.9k Jan 9, 2023
Airbnb's Swift Style Guide.

Airbnb Swift Style Guide Goals Following this style guide should: Make it easier to read and begin understanding unfamiliar code. Make code easier to

Airbnb 1.8k Jan 3, 2023
LinkedIn's Official Swift Style Guide

Swift Style Guide Make sure to read Apple's API Design Guidelines. Specifics from these guidelines + additional remarks are mentioned below. This guid

LinkedIn 1.4k Jan 5, 2023
The Official raywenderlich.com Swift Style Guide.

The Official raywenderlich.com Swift Style Guide. Updated for Swift 5 This style guide is different from others you may see, because the focus is cent

raywenderlich 12.5k Jan 3, 2023
The official Swift style guide for raywenderlich.com.

The Official raywenderlich.com Swift Style Guide. Updated for Swift 5 This style guide is different from others you may see, because the focus is cent

raywenderlich 12.5k Dec 30, 2022
A style guide for Swift.

Table Of Contents Overview Linter Standards Naming Conventions File Structure Types Statement Termination Variable Declaration Self Structs & Classes

Prolific Interactive 171 Oct 4, 2022
LinkedIn's Official Swift Style Guide

Swift Style Guide Make sure to read Apple's API Design Guidelines. Specifics from these guidelines + additional remarks are mentioned below. This guid

LinkedIn 1.4k Dec 13, 2022