menu

Swift Style Guidelines

Naming

Names should be in American English.

See also:

If this is difficult for you to understand at the call-site, then you may have chosen the wrong words. If all else fails, simply use Quick Help (by -clicking the symbol or by selecting it and using the Quick Help inspector) and the resulting documentation will describe its declaration for you.

Capitalization

This one is simple. Types (classes, protocols, typealiases, structs, enums, etc.) are always CapitalizedCamelCase. Instances (lets, vars, cases, etc.) and functions (funcs, dynamic vars, non-anonymous closures, etc.) are always uncapitalizedCamelCase.

When an acronym or initialism like HTTP or JSON is a part of a name, treat it like an English word rather than an abbreviation, even if it’s not pronounceable like a word.

Good Bad
fileprivate class Foo {
    let bar = Bar()
    private var baz: Baz? = nil

    let httpSample: HttpSample? = nil

    func qux(myUrl: URL) {
        bar.hoge(myUrl)
    }
}

enum Fruit {
    case apple
    case blackberry
    case cherry(let isPitted: Bool)

    static let defaultIsPitted = true
}

let globalConstant = "c"

typealias Bar = Norf
fileprivate class _Foo {
    let Bar = bar()
    // Underscores before private fields are not a strict "no", but they are discouraged
    private var _baz: Baz? = nil

    let hTTPSample: HTTPSample? = nil

    func Qux(myURL: URL) {
        Bar.Hoge(myURL)
    }
}

enum fruit {
    case Apple
    case Blackberry
    case Cherry(let is_pitted: Bool)

    static let DEFAULT_IS_PITTED = true
}

let kGlobalConstant = "c"

typealias bar = Norf

Do not use Systems Hungarian notation!

Knowing the type, implementation, etc. in something’s name is not important. If, however, you find that such information is necessary, you may append it as full words to the end of a name, like “nutritionString”, “widthInt”, or “base64ContentWideCString

Do not use Apps Hungarian notation!

Knowing the purpose of something in its name is very important. However, you should prepend it as full words (not short letter abbreviations), like “contentLocalCoordinates”, “unsanitizedUserInput”, or “rowMaximumCount

Grammar

Names should be descriptive and self-documenting (however, that does not mean you should forego documentation). The name of a function, for instance, should describe everything that function does. If that name seems too unwieldy, it’s probably because that function does too much. In that case, split it up into multiple functions, each also with descriptive names.

If your instance, function, or type name is only a few characters long, it probably needs a longer name.

Here are some good rules from Swift.org’s design guidelines:

RULE-OF-THUMB Clarity at the point of use is your most important goal. Entities such as methods and properties are declared only once but used repeatedly. Design APIs to make those uses clear and concise. When evaluating a design, reading a declaration is seldom sufficient; always examine a use case to make sure it looks clear in context.

RULE-OF-THUMB Clarity is more important than brevity. Although Swift code can be compact, it is a non-goal to enable the smallest possible code with the fewest characters. Brevity in Swift code, where it occurs, is a side-effect of the strong type system and features that naturally reduce boilerplate.

RULE-OF-THUMB Write a documentation comment for every declaration. Insights gained by writing documentation can have a profound impact on your design, so don’t put it off.

GOLDEN RULE If you are having trouble describing your API’s functionality in simple terms, you may have designed the wrong API.

It’s important to note that this page uses placeholder names like foo, bar, baz, etc. to name things when the name is unimportant to the example. It’s strongly discouraged to use such obscure andor short names in production code!

Functions

  • Getters are named the same as fields; that is to say they are simply the noun or noun phrase which describes the thing they get. If properties need to be passed in, they are named parameters, not part of the actual function name.
    • Boolean (or other very restricted sets of values) getters are named as assertions about something. They might be prefixed with is/does/etc. or be a present-tense verb or verb phrase.
  • Setters take the same syntax to getters, but with the word “set” prefixing them. Note that it’s preferred to use a var rather than a func to get & set a single value. The incoming parameter which holds the new value should not have a label (use _).
  • Non-Setter Mutators are verbs or phrases describing the mutation they perform
  • Copiers (functions which otherwise act like mutators, but instead of mutating return a new object with the changed data) are present- or past-participle verbs or verb phrases (ending in “ing”, “ed”, etc.) describing the mutation they perform
Good Bad
protocol Funcs {

    // MARK: Getters

    func font(style: FontStyle) -> Font

    func data(for provider: Provider) -> Data

    func element(_ callback: (Element) -> Void)

    func isDataValid(_ data: Data) -> Bool

    var resizes: Bool { get }

    func doesMatch(_ other: Funcs) -> Bool

    func listMatches(in other: Funcs) -> [Match]


    // MARK: Setters

    mutating func setFont(_ font: Font, style: FontStyle)

    mutating func setData(_ data: Data, for provider: Provider)

    func setAsynchronously(with setter: () -> Element)


    // MARK: Mutators

    mutating func resetData(for provider: Provider)

    mutating func increaseFontSize()


    // MARK: Copiers

    func resettingData(for provider: Provider) -> Self

    func increasedFontSize() -> Self
}
protocol Funcs {

    // MARK: Getters

    func getFont(style: FontStyle) -> Font // Don't use "get" for getters

    func FetchDataForProvider(_ provider: Provider) -> Data // "fetch" implementation detail is unnecessary in the signature; function is improperly capitalized

    func get(_ callback: (Element) -> Void) // Get what?

    func validate(_ data: Data) -> Bool // Sounds like it might mutate the data to make it valid

    var resize: Bool { get } // Sounds like it resizes something, possibly returning a success

    func matches(_ other: Funcs) -> Bool // Unclear; are you asserting that this matches the other, or asking for the list of matches?

    func matches(_ other: Funcs) -> [Match] // Same problem as above. Also doesn't compile.


    // MARK: Setters

    mutating func newFont(_ font: Font, style: FontStyle) // Sounds like it returns a new font instead of setting one

    mutating func data(_ data: Data, for provider: Provider) // Sounds like it returns data

    func set(with setter: () -> Element) // Doesn't describe critical behavior (it's asynchronous)


    // MARK: Mutators

    mutating func reset(for provider: Provider) // Doesn't clarify it only resets data

    mutating func inc() // Increment? Incorporate? Increase (Increase what?)?


    // MARK: Copiers

    func resetData(for provider: Provider) -> Self // Sounds like it mutates

    func inc_font() -> Self // Same problem as above and in inc(), uses an underscore, and is unclear whether it mutates
}

Types

Types should not be prefixed; this was a Cocoa pattern used until Swift as a primitive form of namespacing, but since Swift is modular, no prefix is needed.

  • Classes and structs have varied purposes, so they are named in a way that reflects their purpose, using nouns or noun phrases.
  • Protocols define a contract, so there are two approaches:
    • Protocols which define what something is are named exactly like the classes which might implement them; nouns or noun phrases.
    • Protocols which define what something can do are named using present-participle verbs or verb phrases (end in ing, albe, ible, etc.).
  • Enums are named as the singular noun which describes what their cases represent.
  • Typealiases are named just like the type for which they are an alias.
    • Associated types are named just like typealiases.
Good Bad
class BasicDataAccessor: DataAccessor { }
class MainView: NSView { }
class DynamicEncryptionPolicyHandler { }

protocol DataAccessor { }
protocol Encryptable {
    associatedtype Encrypted
}

struct RegistrationWorksheet { }
struct EncryptableFile: Encryptable { }

enum LogSeverity { }
enum ServerErrorCode { }

typealias Label = String
typealias HttpErrorCode = UInt16
typealias Encrypting = Encryptable
class DataAccessImpl: DataAccessProtocol { }
class BHSMainView: NSView { }
class EncPolicy { }

protocol DataAccessProtocol { }
protocol Encrypt {
    associatedtype T
}

struct BHSReg { }
struct EncFile: Encrypt { }

enum LogSeverities { }
enum ErrorCode { }

typealias label = String
typealias HTTPErr = UInt16
typealias Encryptor = Encrypt

Instances

Anything that holds an instance/value (stored fields, enums’ cases, etc.) are named as nouns. An exception can be made for Booleans, which are named as asserting verbs or verb phrases like their function counterparts.

Note that fancy vars may be named like functions.

All instances have the same naming scheme: uncapitalizedCamelCase.

Do not use ALL_CAPS_NAMES, m prefixes, etc.

_underscorePrefixes should only be used if absolutely necessary.

Good Bad
func performAction(sender: Any) { ... }

struct WellDefinedStructure {

    static let shared = WellDefinedStructure(values: ["A", "2", "III"])

    var values: [String]
    private var isBusy = false


    internal init(values: [String]) {
        self.values = values
    }


    func isEqual(to other: WellDefinedStructure) -> Bool { ... }


    var jsonValue: String {
        isBusy = true
        defer { isBusy = false }

        var jsonValue = "{\"values\":["

        jsonValue += values.map { "\"\($0)\"" } .joined(separator: ",")

        return jsonValue + "]}"
    }
}

let wellDefinedStructure = WellDefinedStructure.shared
func performAction(_ sender: Any) { ... }

struct WellDefinedStructure {

    static let SHARED = WellDefinedStructure(vals: ["A", "2", "III"])

    var vals: [String]
    private var m_busy = false


    internal init(vals: [String]) {
        self.vals = vals
    }


    func isEqual(to obj: WellDefinedStructure) -> Bool { ... }


    var json: String {
        m_busy = true
        defer { m_busy = false }

        var str = "{\"values\":["

        str += vals.map { "\"\($0)\"" } .joined(separator: ",")

        return str + "]}"
    }
}

let wds = WellDefinedStructure.SHARED

Plurality

Only collection types (and instances of those types) should be plural (for instance, OptionSets and Arrays). Everything else should be singular.

Good Bad
struct Pizza {
    let size: Size
    let toppings: Toppings


    static let defaultSize = Size.medium
    static let defaultToppings: Toppings = [.cheese, .pepperoni]



    enum Size {
        case small
        case medium
        case large
    }


    struct Toppings: OptionSet {
        let rawValue: UInt8

        static let cheese = Toppings(1 << 0)
        static let pepperoni = Toppings(1 << 1)
        static let bellPeppers = Toppings(1 << 2)
        static let sausage = Toppings(1 << 3)
        static let spinach = Toppings(1 << 4)
    }
}
struct Pizza {
    let size: Sizes
    let toppings: Topping


    static let defaultSize = Sizes.small
    static let defaultToppings: Topping = [.cheese, .pepperoni]



    enum Sizes {
        case small
        case medium
        case large
    }


    struct Topping: OptionSet {
        let rawValue: UInt8

        static let cheese = Topping(1 << 0)
        static let pepperoni = Topping(1 << 1)
        static let bellPeppers = Topping(1 << 2)
        static let sausage = Topping(1 << 3)
        static let spinach = Topping(1 << 4)
    }
}