Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Core Programming Concepts  ›  Lesson

Error Handling

Error Handling 12 minSwift functions that can fail are marked throws, callers mark each risky call with try, and do-catch blocks handle errors, while try? and try! convert them to optionals or crashes.

Error Handling

Saving a hike can fail: the disk is full, the name is empty, or the file is corrupted. An app that pretends nothing can go wrong shows a blank screen or loses data. Swift makes failure part of a function's signature, so callers cannot forget it.

The rule

throws warns, try marks the risk, catch handles the fall.

Errors in Swift are values of any type that conforms to the Error protocol — usually an enum:

enum SaveError: Error {
    case emptyName
    case diskFull
}

A function that can fail is marked throws, and uses throw to fail:

func save(_ hike: Hike) throws {
    guard !hike.name.isEmpty else { throw SaveError.emptyName }
    // ... write to disk, which may also throw
}

A caller must mark each throwing call with try, and handle errors in a do–catch:

do {
    try save(hike)
    showSavedBanner()
} catch SaveError.emptyName {
    showMessage("Give your hike a name.")
} catch {
    showMessage("Could not save: \(error.localizedDescription)")
}

When the first try fails, the rest of the do block is skipped and the matching catch runs. The last plain catch catches anything else and gives you an implicit error constant.

Two shortcuts change a throwing call into something else:

  • try? turns the result into an optional: nil if it threw. Use it when failure just means "no value".
  • try! asserts it will never throw, and crashes if it does. Rarely appropriate.

A function can also rethrow by simply being throws itself and writing try without a do — the error passes up to its caller.

The shortcut

At every try, ask: "Who can do something useful about this failure?" If this code can, catch it here. If only the caller can, mark this function throws and let it pass up.

Loading TrailLog's saved journalStep 1 of 4
  1. The risky call

    let data = try Data(contentsOf: journalURL) can throw if the file is missing.

The trap: wrapping everything in try? and silently throwing away errors the user needed to hear about, such as "disk full".

Drills

Answer fast — trust the rule.

quick drill

What must a caller write before calling a function marked throws?

quick drill

try? Data(contentsOf: url) fails. What is the result?

quick drill

In a do block, the first try throws. What happens to the lines after it?

quick drill

What does try! do if the call throws?

Remember

  • throws warns, try marks the risk, do–catch handles the failure.
  • Shortcut: catch where someone can act; otherwise mark throws and pass it up.
  • Trap: try? hides real problems, and try! crashes.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainHandle a failed import

func importGPX(from url: URL) throws -> [Hike] can throw ImportError.badFormat or a file error. Write how the import screen should call it, showing a specific message for bad format and a general one otherwise, and explain when try? would be the wrong choice here.