Error handling in Swift
Define errors with Error and throws, then handle them with do-catch, try?, and try!.
Read the Korean original on Velog ↗English translation

Code that only describes success hides what happens when an operation fails. Swift makes that possibility visible at the call site with throw and try.
Throwing errors
Use throw when an operation encounters a failure. First, define the possible errors, often with an enum that conforms to Error.
enum MyError: Error {
case firstError
case secondError
}
Mark the function with throws to show that it can fail. Inside it, use throw to report an error when the relevant condition occurs.
func someFunction() throws -> String {
// Failure condition
if isSuccess {
return "Success!"
} else {
// Throw an error
throw MyError.firstError
}
}
A call to a throwing function is marked with try.
try and do-catch
A do-catch statement handles errors thrown by a try expression. The catch clauses specify how to respond to particular failures. A throwing caller can also propagate an error to its own caller.
// Call the throwing function with try
do {
let result = try someFunction()
} catch MyError.firstError {
// Handle the specific error
} catch {
// Handle other errors
}
A switch inside catch is another way to handle different error cases.
do {
let result = try someFunction()
} catch {
// Handle each error case
switch error {
case MyError.firstError:
print("first")
case MyError.secondError:
print("second")
default:
print("default")
}
}
try? converts failure into nil and returns a successful result as an optional. It can be used without a do-catch block when the specific error is not needed.
// Return nil on failure
let result = try? someFunction()
Use try! only when you are certain the operation cannot throw in that context. If it does, execution stops with a runtime error.
// Trap if the call throws
let result = try! someFunction()