ProgrammingiOS Developer

Describe how error handling works in Swift. What types of errors are there, what methods are available for handling them, when is it preferable to use throw/catch, and when is it better to use Result?

Pass interviews with Hintsage AI assistant

Answer.

Swift supports a strict error handling system through the Error protocol and the throw, try, catch constructs. You can define your own error types by conforming to Error:

enum NetworkError: Error { case noInternet case serverError(code: Int) case unknown }

Functions that can throw an error are declared with throws:

func fetchData() throws -> Data { // ... throw NetworkError.noInternet }

Errors can be handled using a do-catch block:

do { let data = try fetchData() // Working with the data } catch NetworkError.noInternet { print("No internet") } catch { print("Another error: \(error)") }

An alternative approach is the Result<T, Error> type, which allows you to return either a result or an error without needing try-catch:

func fetchData() -> Result<Data, NetworkError> { // ... return .failure(.noInternet) } let result = fetchData() switch result { case .success(let data): // OK case .failure(let err): // Handling the error }

When to use:

  • Use try/catch if the error is critical and cannot be ignored.
  • Use Result if the function is asynchronous or when it's convenient to pass the error "out" without exceptions.

Trick question.

Question: "Can you throw and catch errors of any type, for example, strings or numbers?"

Answer: No, in Swift you can only throw types that conform to the Error protocol.

// Incorrect: throw "StringError" // The compiler will not allow this // Correct: struct MyError: Error {} throw MyError()

Examples of real errors due to ignorance of the nuances of the topic.


Story

In a REST API client project, an error was thrown as a string (throw "No data"). The code compiled in JavaScript, but after being translated to Swift, a fatal compilation error occurred.


Story

A developer returned an error via optional values (return nil on error) instead of through throw/Result. As a result, error details were lost, making it difficult to handle them correctly — silent fails occurred.


Story

Analysis showed that in several places in the app, identical errors were not grouped into a single Error type. As a result, the application handled similar failures differently, with the UI displaying various messages for the same error — making it difficult to maintain and test.