An error (exception) is an unexpected event that occurs during program execution. For example,
var numerator = 10
var denominator = 0
// try to divide a number by 0
var result = numerator / denominator // error code
Here, we are trying to divide a number. So this type of error causes the abnormal termination of the program.
Steps For Error Handling in Swift
- Create an enum that represents the types of errors.
- Create a throwing function using the
throws
keyword. - Call the function using the
try
keyword. - Wrap the code with
try
in thedo {...}
block and add thecatch {...}
block to handle all errors.
1. Create enum of Errors
In Swift, we need to create an enum that represents the type of errors we may encounter while writing the program.
The enum we create must conform to the Error
protocol so that we can throw an error value inside the function.
Let's see an example,
enum DivisionError: Error {
case dividedByZero
}
Here, we have created an enum named DivisionError
with the value dividedByZero
.
Since DivisionError
conforms to the Error
protocol, we'll now be able to throw the error value of the enum.
2. Create a Throwing Function
In order to throw errors, we need to create a throwing function using the throws
keyword.
Then we use the throw
statement inside the function to throw a particular error represented by the enum. For example,
// create throwing function using throws keyword
func division(numerator: Int, denominator: Int) throws {
// throw error if divide by 0
if denominator == 0 {
throw DivisionError.dividedByZero
}
...
}
Here, we have created a throwing function named division()
using the throws
keyword. The function throws the dividedByZero
value of the DivisionError
enum if denominator == 0
Now, based on the value passed during the function call, the function throws an error if the error condition is met.
Note: The throw
keyword has the same effect as the return
keyword. return
returns some value from the function, whereas throw
returns error value from the function.
3. Function Call Using try Keyword
In Swift, we use the try
keyword while calling the throwing function. It indicates that a function can throw an error. For example,
// call throwing function using try keyword
try division(numerator: 10, denominator: 0)
However, the error handling process is still incomplete. If we run the program now, we'll get an error message: An error was thrown and was not caught
So, in order to catch the thrown error, we use the do-catch
statement.
4. Handling Errors Using do-catch Statement
In Swift, we wrap the try
code in the do
block and add the catch
block to handle all errors. For example,
do {
try division(numerator: 10, denominator: 0)
...
}
catch DivisionError.dividedByZero {
// statement
}
Here, we have called the throwing function division()
from within the do
block and attached the catch
block to catch the error in case the function throws one.
The above catch
block is executed based on the enum value of DivisionError
.
This is the final step to handle possible errors that may occur in our program.
Example: Swift Error Handling
// create an enum with error values
enum DivisionError: Error {
case dividedByZero
}
// create a throwing function using throws keyword
func division(numerator: Int, denominator: Int) throws {
// throw error if divide by 0
if denominator == 0 {
throw DivisionError.dividedByZero
}
else {
let result = numerator / denominator
print(result)
}
}
// call throwing function from do block
do {
try division(numerator: 10, denominator: 0)
print("Valid Division")
}
// catch error if function throws an error
catch DivisionError.dividedByZero {
print("Error: Denominator cannot be 0")
}
Output
Error: Denominator cannot be 0
In the above example,
DivisionError
is an enumdivision()
is a throwing function- the
do-catch
statement handles the error
We have used try
to pass values to the throwing function
try division(numerator: 10, denominator: 0)
to check if the passed values meet the error condition or not.
If the error condition is
- met - the throwing function throws the error, which is caught by the catch block.
- not met - the
else
statement inside throwing function andprint
statement inside thedo
block are executed.
Disable Error Handling
In Swift, sometimes we can be confident that the throwing function won't throw an error at runtime.
In that case, we can write try!
during the function call to disable the error handling. For example,
enum DivisionError: Error {
case dividedByZero
}
func division(numerator: Int, denominator: Int) throws {
if denominator == 0 {
throw DivisionError.dividedByZero
}
else {
let result = numerator / denominator
print("Result:", result)
}
}
// disable error handling
try! division(numerator: 10, denominator: 5)
Output
Result: 2
In the above example, we have used try!
during the function call to disable the error handling.
try! division(numerator: 10, denominator: 5)
Here, since we have assigned value 5 to denominator, we know that the program will not throw an error. So we have disabled the error handling.
Also notice that when we use try!
, we don't need to use the do-catch
statement.
Note: If we use try!
and there is an error, our app will simply crash.
Causes of Error in Swift
An error can occur for many reasons. Some of them are:
- Invalid user input
- Device failure
- Loss of network connection
- Physical limitations (out of disk memory)
- Code errors
- Opening an unavailable file
Since the errors abnormally terminate the execution of a program, it is important to handle these kinds of errors.