Variables & Types
let name = "Alice"Immutable constantvar count = 0Mutable variablelet x: Int = 42Explicit type annotationInt, Double, Float, Bool, String, CharacterCommon value typeslet big: Int64 = 9_000_000_000Underscore separators in literalslet hex = 0xFF; let bin = 0b1010Hex and binary literalslet x: Int? = nilOptional - may hold a value or nillet x: Int! = 42Implicitly unwrapped optional - use sparinglytypealias Meters = DoubleType aliaslet tuple = (200, "OK")Unnamed tuplelet res = (code: 200, msg: "OK"); res.codeNamed tuple - access by labelStrings
"Hello, \(name)!"String interpolation"""multi\nline"""Multi-line string literals.countNumber of characterss.isEmptyTrue if empty strings.uppercased() / s.lowercased()Change cases.hasPrefix("Hello") / s.hasSuffix("!")Prefix/suffix checks.contains("world")Substring checks.replacingOccurrences(of: "a", with: "b")Replace substrings.components(separatedBy: ",")Split string into arrays.trimmingCharacters(in: .whitespaces)Trim whitespaceInt("42")Parse string to Int - returns OptionalString(42)Convert Int to StringOptionals
if let name = optName { }Optional binding - unwrap if non-nilif let name { }Shorthand optional binding (Swift 5.7+)guard let name = optName else { return }guard let - exit scope if nillet n = opt ?? 0Nil-coalescing - use default if nilopt?.propertyOptional chaining - nil if opt is nilopt!Force unwrap - crashes if nilif let a = opt1, let b = opt2 { }Bind multiple optionalswhile let item = iter.next() { }Optional binding in while looplet x = try? parse(s)Convert throwing call to OptionalControl Flow
if x > 0 { } else if x < 0 { } else { }if / else if / elseswitch x { case 1: ... case 2, 3: ... default: ... }switch - no fallthrough by defaultswitch x { case let n where n > 0: ... }switch with where clauseswitch shape { case .circle(let r): ... }switch on enum with associated valuefallthroughExplicit fallthrough to next casefor i in 0..<10 { }Half-open range (0 to 9)for i in 0...10 { }Closed range (0 to 10 inclusive)for item in array { }Iterate over collectionfor (i, v) in array.enumerated() { }Iterate with indexfor (k, v) in dict { }Iterate over dictionarywhere i.isMultiple(of: 2)for loop filterwhile x > 0 { }while looprepeat { } while x > 0do-while equivalentbreak / continueExit loop / skip iterationguard condition else { return }Early exit - bindings available afterdefer { cleanup() }Run code when scope exits - LIFO orderFunctions
func greet(name: String) -> String { "Hello \(name)" }Function with argument labelgreet(name: "Alice")Call with argument labelfunc greet(_ name: String)_ removes external labelfunc move(from src: String, to dst: String)External and internal labelsfunc greet(name: String = "World")Default parameter valuefunc sum(_ nums: Int...) -> IntVariadic parameterfunc swap(_ a: inout Int, _ b: inout Int)inout - modify caller variableswap(&x, &y)Call inout function - pass with &func apply(_ fn: (Int) -> Int, to x: Int) -> IntFunction parameterlet double: (Int) -> Int = { $0 * 2 }Closure with shorthand argument name{ x, y in x + y }Closure with named parametersarray.sorted { $0 < $1 }Trailing closure syntaxfunc id<T>(_ x: T) -> TGeneric function@discardableResult func load() -> DataSuppress unused-result warningClasses, Structs & Enums
struct Point { var x: Double; var y: Double }Struct - value type, copied on assignmentclass User { var name: String; init(name: String) { self.name = name } }Class - reference typeclass Admin: User { override func greet() { } }Class inheritancefinal class Token { }final - cannot be subclassedrequired init()Required initializer - subclasses must implementconvenience init() { self.init(name: "default") }Convenience initializerdeinit { cleanup() }Deinitializer - called on deallocation (classes only)var computed: Int { get { } set { } }Computed propertyvar lazy: Data = { loadData() }()Lazy property - initialized on first accesswillSet / didSetProperty observersstatic var count = 0Type propertymutating func reset()mutating - struct method that modifies selfenum Direction { case north, south, east, west }Enumenum Result { case success(Data); case failure(Error) }Enum with associated valuesenum Planet: Int { case mercury = 1, venus, earth }Raw value enumPlanet(rawValue: 3)Create enum from raw value - returns Optionalindirect enum Tree { case leaf(Int); case node(Tree, Tree) }Recursive enumProtocols & Generics
protocol Greetable { func greet() -> String }Protocol definitionstruct User: Greetable, Codable { }Conform to multiple protocolsextension User: Greetable { func greet() -> String { name } }Protocol conformance in extensionprotocol Container { associatedtype Item }Protocol with associated typefunc printAll<T: Greetable>(_ items: [T])Generic with protocol constraintfunc printAll(_ items: some Greetable)some - opaque type (Swift 5.7+)func printAll(_ items: any Greetable)any - existential typeextension Array where Element: ComparableConstrained extensionEquatable, Comparable, Hashable, CodableCommon standard protocolsCodable = Encodable & DecodableCodable for JSON encoding/decodingError Handling
enum AppError: Error { case notFound; case invalid(String) }Custom error typefunc load() throws -> DataThrowing functionfunc load() async throws -> DataAsync throwing functiontry load()Call throwing functiontry? load()Convert throw to Optional - nil on errortry! load()Force try - crashes on errordo { let d = try load() } catch AppError.notFound { } catch { print(error) }do-catchcatch let e as AppErrorCatch and cast to specific error typeResult<Data, Error>Result type - .success or .failureConcurrency (async/await)
func fetch() async -> DataAsync functionlet data = await fetch()Await async resultTask { await doWork() }Unstructured async taskTask.detached { await doWork() }Detached task - no actor contextasync let a = fetchA(); async let b = fetchB(); let (x, y) = await (a, b)Concurrent bindingawait withTaskGroup(of: Int.self) { group in group.addTask { ... } }Task group - structured concurrencyactor Bank { var balance = 0 }Actor - isolated mutable stateawait bank.deposit(100)Cross-actor call - must await@MainActor func updateUI()Run on main threadnonisolated func pureCalc()Opt out of actor isolationAsyncStream<Int>Async sequence - model streams with async/awaitfor await value in stream { }Consume async sequence