SWIFT

Swift Try Catch: Syntax, Usage, and Examples

Swift try catch is part of Swift’s error handling system. It allows you to attempt code that might fail and handle any errors that occur. Instead of crashing, your app can respond to problems gracefully—whether you're reading a file, decoding JSON, or connecting to an API.

How to Use Try Catch in Swift

Swift uses a combination of do, try, and catch to handle errors. You place potentially failing code inside a do block and handle errors in a catch block.

Basic Syntax of Try Catch Swift

do {
    try someFunctionThatThrows()
} catch {
    print("An error occurred: \(error)")
}

The try keyword marks a function that can throw an error. If it does, the control passes to the catch block. If not, execution continues normally.

Defining Your Own Throwing Functions

Here’s how to create a function that can throw:

enum FileError: Error {
    case fileNotFound
}

func readFile(named name: String) throws -> String {
    guard name == "data.txt" else {
        throw FileError.fileNotFound
    }
    return "File contents"
}

Now you can use this with Swift try catch:

do {
    let contents = try readFile(named: "wrong.txt")
    print(contents)
} catch {
    print("Failed to read file.")
}

If readFile throws fileNotFound, the catch block handles it.

When to Use Try Catch in Swift

Swift try catch comes in handy any time you call a function that can fail. Use it when:

  • Reading or writing files that might be missing or unreadable.
  • Decoding JSON that may be incorrectly formatted.
  • Performing network calls that can fail due to connection issues or bad responses.
  • Using APIs that mark their methods with throws.
  • Validating inputs or processing data that might be invalid.

Try catch Swift gives you control over these failure points so you can inform users or take alternative actions.

Examples of Try Catch Swift in Practice

Reading a File with Error Handling

enum FileError: Error {
    case missing
}

func openFile(name: String) throws -> String {
    if name != "document.txt" {
        throw FileError.missing
    }
    return "This is the file content."
}

do {
    let file = try openFile(name: "notes.txt")
    print(file)
} catch {
    print("Could not open file.")
}

This example uses do try catch Swift logic to manage file-related issues.

Parsing JSON with Do Try Catch Swift

struct User: Decodable {
    let name: String
}

let json = """
{ "name": "Taylor" }
""".data(using: .utf8)!

do {
    let user = try JSONDecoder().decode(User.self, from: json)
    print("Hello, \(user.name)")
} catch {
    print("Failed to decode JSON")
}

JSON decoding is one of the most common reasons to use try catch Swift in modern iOS development.

Using Multiple Catch Blocks

You can write multiple catch blocks to handle specific error types:

enum NetworkError: Error {
    case timeout
    case noConnection
}

func fetchData() throws {
    throw NetworkError.timeout
}

do {
    try fetchData()
} catch NetworkError.timeout {
    print("Request timed out.")
} catch NetworkError.noConnection {
    print("No internet connection.")
} catch {
    print("An unknown error occurred.")
}

This approach lets you respond differently to different failure scenarios.

Learn More About Try Catch in Swift

Optional Try (try?)

Sometimes you want to try something but ignore the error if it fails. That’s where try? comes in. It returns an optional value: the result if the function succeeds, or nil if it fails.

func convert(_ input: String) throws -> Int {
    guard let number = Int(input) else {
        throw NSError(domain: "", code: 0)
    }
    return number
}

let value = try? convert("42")  // value is Optional(42)
let fail = try? convert("abc")  // fail is nil

Use try? when failure isn’t critical and you’re okay with silently failing.

Forced Try (try!)

If you're sure a function won’t throw, or you're okay with crashing if it does, use try!.

let result = try! convert("123")

Avoid try! unless you’re absolutely sure—because if an error is thrown, your app crashes.

Re-throwing Functions

You can create functions that accept other throwing functions and re-throw any errors.

func runTask(_ task: () throws -> Void) rethrows {
    try task()
}

This helps you write wrapper functions that preserve the ability to throw errors.

Nesting Try Catch Swift Blocks

You can nest do try catch inside other blocks. For example:

func performTask() {
    do {
        try fetchData()
    } catch {
        print("Task failed: \(error)")
    }
}

Each block only handles the specific errors thrown inside it.

Custom Error Messages

Inside catch, you get an error object. You can inspect or convert it:

catch let err as MyCustomError {
    print("Specific error: \(err)")
} catch {
    print("General error: \(error.localizedDescription)")
}

This helps with debugging and user feedback.

Throwing Initializers

You can mark initializers with throws, too:

struct Profile {
    let age: Int

    init(age: Int) throws {
        guard age > 0 else { throw NSError(domain: "", code: 0) }
        self.age = age
    }
}

do {
    let profile = try Profile(age: 25)
    print("Age: \(profile.age)")
} catch {
    print("Invalid age")
}

This approach helps with model validation and setup.

Swift Error Handling vs Objective-C

In Objective-C, you check NSError pointers. Swift try catch replaces that with a modern, cleaner syntax. Errors become typed values, not just return codes.

Best Practices for Try Catch Swift

  • Always handle errors where they occur or bubble them up responsibly.
  • Use specific catch blocks when you can for clearer logic.
  • Don’t overuse try!—crashes hurt user experience.
  • Use try? only when silent failure is acceptable.
  • Prefer custom error types with meaningful names and cases.
  • Add context when printing or logging errors—raw error isn’t always helpful.
  • Keep throwing functions small and focused.

Swift try catch gives you a safe, expressive way to deal with failures without cluttering your code with error codes or flags. From decoding a response to validating a file, handling errors the Swift way makes your app more stable and easier to debug.

Learn to Code in Swift for Free
Start learning now
button icon
To advance beyond this tutorial and learn Swift by doing, try the interactive experience of Mimo. Whether you're starting from scratch or brushing up your coding skills, Mimo helps you take your coding journey above and beyond.

Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.

You can code, too.

© 2025 Mimo GmbH