Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The do-catch statement is a control flow mechanism in Swift used to handle recoverable errors. It evaluates expressions that can throw an error (annotated with the throws keyword) and transfers execution to a designated catch block if an error is propagated, utilizing Swift’s Error protocol for pattern matching.

Syntax Structure

The statement consists of a single do block followed by one or more catch clauses.
do {
    let result = try throwingFunction()
    // Execution continues here only if no error is thrown
} catch Pattern1 {
    // Executes if the thrown error matches Pattern1
} catch Pattern2 where condition {
    // Executes if the error matches Pattern2 AND the boolean condition evaluates to true
} catch {
    // Catch-all block for any error not matched above
}

Technical Mechanics

Lexical Scoping The do block introduces a new lexical scope. Variables or constants declared within the do block are inaccessible to the subsequent catch blocks and the outer scope. Control Transfer When an expression prefixed with try throws an error, the runtime immediately suspends execution of the do block. Any statements following the throwing expression within that block are skipped. Control is transferred to the first catch clause that successfully matches the thrown error. Sequential Pattern Matching catch clauses are evaluated sequentially from top to bottom. The runtime executes only the first block whose pattern matches the thrown error. Because of this top-down evaluation, more specific error patterns must be placed before broader or catch-all patterns. Implicit Error Binding If a catch clause is provided without an explicit pattern, Swift implicitly binds the thrown error to a local constant named error of type any Error.
do {
    try performAction()
} catch {
    print(error.localizedDescription) // 'error' is implicitly provided by the compiler
}
Exhaustiveness Swift requires error handling to be exhaustive. A do-catch statement must either handle every possible error that can be thrown, or the enclosing function itself must be marked with throws to propagate unhandled errors up the call stack. A generic catch block without a pattern guarantees exhaustiveness.

Advanced Pattern Matching

Swift allows granular error interception using enumeration cases, associated values, and type checking within catch clauses.
enum SystemError: Error {
    case timeout
    case networkFailure(code: Int)
}

do {
    try executeTask()
} catch SystemError.timeout {
    // Matches a specific enum case
} catch SystemError.networkFailure(let code) where code == 404 {
    // Matches a specific case, extracts the associated value, and applies a where clause
} catch is SystemError {
    // Type-checking match: catches any SystemError not matched by preceding clauses
} catch let customErrorName {
    // Catch-all that explicitly binds the error to a custom identifier instead of 'error'
}

Relationship with try Variants

The do-catch block is strictly required when using the standard try operator in a non-throwing context. It is not required when using:
  • try?: Converts the throwing expression into an Optional, returning nil if an error is thrown, discarding the underlying error object.
  • try!: Disables error propagation entirely, forcing a runtime crash if an error is thrown.
Master Swift with Deep Grasping Methodology!Learn More