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.
throws
keyword.try
keyword.try
in the do {...}
block and add the catch {...}
block to handle all 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.
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.
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.
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.
// 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 functiondo-catch
statement handles the errorWe 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
else
statement inside throwing function and print
statement inside the do
block are executed.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.
An error can occur for many reasons. Some of them are:
Since the errors abnormally terminate the execution of a program, it is important to handle these kinds of errors.