Swift & iOS

A grouped lookup for Swift keywords, declarations, modifiers, operators, and language syntax.

~13 min reading
Suggest content

Swift Keywords and Syntax Quick Reference

🟪 Syntax · 🟦 Types/APIs · 🟩 Correct pattern · 🟥 Bug · 🟨 Gotcha · 🧠 Explanation

This is a grouped reference for the Swift 6.4 language. Some words are reserved everywhere; others are only special in a grammar position. A spelling being used as a keyword in one declaration does not always prevent using it as a name elsewhere. Escape a reserved spelling with backticks only when there is a good interoperability reason.

Declarations and modifiers

KeywordTypical role
associatedtypeDeclares a protocol-associated type
borrowingSpecifies a non-consuming parameter ownership convention
actorDeclares an actor-isolated reference type
classDeclares a reference type; also marks overridable type members
consumingSpecifies that a parameter consumes a value
deinitDefines class/actor cleanup before deallocation
enumDeclares a type with a finite set of cases, possibly carrying values
extensionAdds methods, computed properties, conformances, and nested types
fileprivateMakes a declaration accessible within its source file
funcDeclares a function or method
importMakes declarations from a module available
initDeclares an initializer
inoutAllows a function to mutate a caller's variable
internalDefault access; visible within the current module
letDeclares an immutable binding
macroDeclares a Swift macro
nonisolatedMarks a declaration as not isolated to its actor/global actor
openAllows access and subclassing/overriding outside the defining module
operatorDeclares a custom operator
precedencegroupDefines precedence and associativity for operators
privateRestricts access to the enclosing declaration scope
protocolDeclares a set of requirements
publicExposes a declaration to importing modules
rethrowsCan throw only when a throwing function argument throws
staticDeclares a type-level member or a non-overridable class member
structDeclares a value type
subscriptDefines indexed get/set syntax
typealiasGives an existing type another name
varDeclares mutable storage or a computed property

actor and macro are special in their declaration grammar. async, throws, access control, and ownership modifiers also appear in the declaration forms below.

SWIFT
import Foundation
​
protocol IdentifiableRecord {
    associatedtype ID: Hashable
    var id: ID { get }
}
​
struct Record: IdentifiableRecord {
    let id: UUID
    private(set) var title: String
}
​
actor RecordStore {
    private var records: [UUID: Record] = [:]
    func record(id: UUID) -> Record? { records[id] }
}

Control-flow and statement keywords

break, case, catch, continue, default, defer, do, else, fallthrough, for, guard, if, in, repeat, return, switch, throw, where, while.

SWIFT
import Foundation
​
struct Record {
    let title: String
}
​
enum LookupError: Error {
    case missing
}
​
func title(for record: Record?) throws -> String {
    guard let record else { throw LookupError.missing }
​
    defer { print("finished lookup") }
​
    switch record.title.count {
    case 0: return "Untitled"
    case 1...20 where record.title.first?.isUppercase == true:
        return record.title
    default:
        return String(record.title.prefix(20))
    }
}
  • guard exits the current scope unless its condition succeeds.
  • defer runs when the current scope exits. In Swift 6.4 async functions can also use asynchronous cleanup inside defer.
  • fallthrough explicitly continues into the next switch case. Most Swift switches should use independent cases instead.
  • where adds a condition to a pattern or generic constraint.
  • repeat begins a repeat-while loop, which checks its condition after its body.

Expression and type keywords

Any, as, await, catch, false, is, nil, rethrows, self, Self, super, throw, throws, true, try.

SWIFT
import Foundation
​
func decode<T: Decodable>(_ type: T.Type, from data: Data) throws -> T {
    try JSONDecoder().decode(type, from: data)
}
​
func loadValue() async throws -> Any { "ready" }
​
func use(_ value: Any) async throws {
    let loaded = try await loadValue()
    if loaded is String { /* type test */ }
    let string = value as? String      // conditional cast
    let required = value as! String    // forced cast; use only for a proven invariant
    let unknown: Any = 42              // any value, without a specific protocol contract
}
  • try marks a throwing call, try? converts failure to an optional, and try! traps on failure.
  • await marks a possible suspension while calling asynchronous work.
  • Self is the current type; self is the current value/instance.
  • Any can hold any value. any SomeProtocol is an existential with a protocol contract.
  • as? is a conditional cast; as! traps if the cast fails. Avoid force casts in normal control flow.

Context-sensitive keywords

These spellings are special in particular grammar positions and can be ordinary identifiers in other positions:

GroupWords
Access / dispatchconvenience, dynamic, final, override, required, package
PropertiesdidSet, get, lazy, set, willSet
Operators / enumsassociativity, indirect, infix, left, none, postfix, precedence, prefix, right
Mutation / ownershipmutating, nonmutating, weak, unowned
Concurrency / type spellingasync, some, Protocol, Type
Optional Objective-C protocol membersoptional
SWIFT
import SwiftUI
​
@MainActor
final class SettingsModel {
    lazy var formatter = DateFormatter()
    private(set) var title = "Settings" {
        didSet { print("title changed") }
    }
​
    func refresh() async throws {
        title = try await fetchTitle()
    }
​
    private func fetchTitle() async throws -> String { "Settings" }
}
​
func makeLabel() -> some View { Text("Ready") }

The compiler's current language reference is the final authority for context-sensitive spellings. distributed, sending, and isolation-related terms also appear in newer concurrency grammar.

Directives and compiler macros

The following # forms are language directives or macros, not ordinary declaration keywords:

FormPurpose
#if, #elseif, #else, #endifConditional compilation
#available, #unavailableRuntime OS availability checks
#keyPath, #selectorObjective-C/KVO interoperability
#sourceLocationAdjust source location information
#colorLiteral, #imageLiteral, #fileLiteralXcode literal support
#file, #fileID, #filePath, #function, #line, #column, #dsohandleSource/compiler context values
#warning(...), #error(...)Emit build diagnostics
#PreviewDeclare a SwiftUI preview (macro)
#expect, #require, @Test, @SuiteSwift Testing macros/attributes
SWIFT
if #available(iOS 17, *) {
    // Use an API introduced in iOS 17 or later.
} else {
    // Keep a fallback for the deployment target.
}
​
#if DEBUG
print("Debug build")
#endif

@Observable, @State, @MainActor, and @available use attribute syntax. The @ forms are not keywords in the same category as if or func.

Common attributes and property wrappers worth recognizing include @MainActor, @concurrent, @Sendable, @Observable, @State, @Binding, @Bindable, @available, @objc, @discardableResult, @inlinable, and Swift 6.4's @diagnose for source-level warning control. The @ syntax does not make every attribute part of the Swift language grammar; many are provided by the standard library or frameworks.

Common punctuation with meaning

SyntaxMeaning
?Optional type (User?), optional chaining (user?.name), or ternary conditional
!Force unwrap (user!) or logical negation (!isReady)
->Function result type
_Wildcard pattern or ignored argument label
... / ..<Closed / half-open range
&Inout argument marker or protocol composition separator
\.nameKey path
$valueProperty-wrapper projection, commonly a Binding or publisher
\(value)String interpolation
... in a declarationVariadic parameter syntax (String...)

Swift 6.4 syntax worth recognizing

These are recent language capabilities; use them only when the project's compiler and language mode support them:

SWIFT
// Optional opaque/existential type spelling in Swift 6.4:
func maybeView(_ show: Bool) -> some View? {
    show ? Text("Ready") : nil
}
​
// Explicit ownership conventions for an advanced noncopyable type:
struct Resource: ~Copyable { let handle: Int }
func inspect(_ resource: borrowing Resource) { print(resource.handle) }
func consume(_ resource: consuming Resource) { print(resource.handle) }
​
// Module selector when two imports export the same name:
let task = Swift::Task { /* work */ }
​
// Async cleanup is awaited when the scope exits (in an async function):
func useResource() async throws {
    let resource = try await openResource()
    defer { await resource.close() }
    try await resource.process()
}

Naming and safe defaults

  • Prefer let; use var only when reassignment or mutation is required.
  • Prefer guard let for required input validation and if let for optional branches.
  • Prefer as? and try? only when a failed cast/operation is a normal optional outcome.
  • Keep access control narrow: private inside a type, internal inside a module, package inside a Swift package, public for APIs, and open only when external subclassing is part of the API contract.
  • Avoid !, as!, try!, and fatalError for ordinary recoverable failures.

References