Airbnb Swift Style Guide

Goals

Following this style guide should:

  • Make it easier to read and begin understanding unfamiliar code.
  • Make code easier to maintain.
  • Reduce simple programmer errors.
  • Reduce cognitive load while coding.
  • Keep discussions on diffs focused on the code’s logic rather than its style.

Note that brevity is not a primary goal. Code should be made more concise only if other good code qualities (such as readability, simplicity, and clarity) remain equal or are improved.

Guiding Tenets

  • This guide is in addition to the official Swift API Design Guidelines. These rules should not contradict that document.
  • These rules should not fight Xcode’s ^ + I indentation behavior.
  • We strive to make every rule lintable:
    • If a rule changes the format of the code, it needs to be able to be reformatted automatically (either using SwiftLint autocorrect or SwiftFormat).
    • For rules that don’t directly change the format of the code, we should have a lint rule that throws a warning.
    • Exceptions to these rules should be rare and heavily justified.

Table of Contents

  1. Xcode Formatting
  2. Naming
  3. Style
    1. Functions
    2. Closures
    3. Operators
  4. Patterns
  5. File Organization
  6. Objective-C Interoperability
  7. Contributors
  8. Amendments

Xcode Formatting

You can enable the following settings in Xcode by running this script, e.g. as part of a “Run Script” build phase.

  • (link) Each line should have a maximum column width of 100 characters.

    Why?

    Due to larger screen sizes, we have opted to choose a page guide greater than 80

  • (link) Use 2 spaces to indent lines. SwiftFormat: indent

  • (link) Trim trailing whitespace in all lines. SwiftFormat: trailingSpace


back to top

Naming

  • (link) Use PascalCase for type and protocol names, and lowerCamelCase for everything else. SwiftLint: type_name

    protocol SpaceThing {
      // ...
    }
    
    class SpaceFleet: SpaceThing {
    
      enum Formation {
        // ...
      }
    
      class Spaceship {
        // ...
      }
    
      var ships: [Spaceship] = []
      static let worldName: String = "Earth"
    
      func addShip(_ ship: Spaceship) {
        // ...
      }
    }
    
    let myFleet = SpaceFleet()

    Exception: You may prefix a private property with an underscore if it is backing an identically-named property or method with a higher access level

    Why?

    There are specific scenarios where a backing a property or method could be easier to read than using a more descriptive name.

    • Type erasure

    <div class="highlight highlight-source-swift position-relative" data-snippet-clipboard-copy-content="public final class AnyRequester: Requester {

    public init(_ requester: T) where T.ModelType == ModelType {
    _executeRequest = requester.executeRequest
    }

    @discardableResult
    public func executeRequest(
    _ request: URLRequest,
    onSuccess: @escaping (ModelType, Bool) -> Void,
    onFailure: @escaping (Error) -> Void)
    -> URLSessionCancellable
    {
    return _executeRequest(request, session, parser, onSuccess, onFailure)
    }

    private let _executeRequest: (
    URLRequest,
    @escaping (ModelType, Bool) -> Void,
    @escaping (NSError) -> Void)
    -> URLSessionCancellable

    }
    “>

    public final class AnyRequester<ModelType>: Requester {
    
      public init<T: Requester>(_ requester: T) where T.ModelType == ModelType {
        _executeRequest = requester.executeRequest
      }
    
      @discardableResult
      public func executeRequest(
        _ request: URLRequest,
        onSuccess: @escaping (ModelType, Bool) -> Void,
        onFailure: @escaping (Error) -> Void)
        -> URLSessionCancellable
      {
        return _executeRequest(request, session, parser, onSuccess, onFailure)
      }
    
      private let _executeRequest: (
        URLRequest,
        @escaping (ModelType, Bool) -> Void,
        @escaping (NSError) -> Void)
        -> URLSessionCancellable
    
    }