Swift Error Handling

In swift, error handling is the process that is used to respond and recover from error conditions in the application. Swift provides us the support to capture and manipulate errors in an application at runtime.

 

Generally in swift, the major things which cause to fail our code are user input, connections, and links associated with our code. Suppose if we make a calculator app in which we can perform a calculation of two numbers and it works fine when we entered valid numbers as an input, but when the user enters invalid input like an entered string instead of number then our code will fail and gives an error.

 

In this situation, we need to catch these kinds of errors and display a valid message to the user like “invalid input”.

 

By using the error handling process in swift we can capture the errors thrown by an application and perform some custom operations to show custom messages to the user based on our requirements.

Swift Representing and Throwing Errors

Generally, in swift errors are represented by the value of types that follow the standards of Error protocol. The Error protocol tells the compiler that any data structure which compiles to the protocols can be used for error handling purpose.

 

In swift, enumeration is the best suit for grouping error conditions. We can represent or declare our errors in enumeration by its name and value.

 

Following is the sample way of defining custom errors in the swift enumeration.

 

enum UserError :  Error {

case InvalidId

case InvalidName

}

We can throw an error when the normal flow of application cannot continue or something unexpected is happing like as shown below

 

throw UserError.InvalidId

Following is the example in which we declare our custom errors in enumeration and throwing errors when the normal flow of execution fails and catching exceptions using do…catch statements.

 

enum UserError :  Error {

case InvalidId

case InvalidName

}

func userdetails(id : Int, name: String) throws

{

if id == 0 {

throw UserError.InvalidId

}

if name == "" {

throw UserError.InvalidName

}

}

do {

try userdetails(id: 0, name: "Suresh")

} catch UserError.InvalidId {

print("Invalid Id")

}

catch UserError.InvalidName {

print("Invalid Name")

}

If you observe above example we added a custom errors to enumeration and throwing an exceptions when it failed to match certain defined conditions.

 

When we run the above program in swift playground we will get a result like as shown below

 

Invalid Id

This is how we can represent and throw errors in a swift programming language based on our requirements.

Swift Handling Errors

In swift, when the application throws an error we need to write our custom piece of code to handle the exception errors like showing custom error message about failure or an alternative way to proceed further in the application.

 

Generally, in swift we can handle the errors in different ways like

 

  • Using do…catch statement
  • Send an error from function to the code that calls the function
  • Using an optional value
  • Assert that error will not occur

In swift, we can identify the places of throwing an error in our code by using try or try? or try! Keywords just before the code that calls the function, method or an initializer that can throw an error.

 

Now we will see how to handle errors in application using different ways in swift programming language.

Swift Propagating Errors Using Throwing Functions

In swift we can indicate a function, method or initializer can throw an error by adding throws keywords in the function declaration and after its parameters. In case the function is having return type then we need to write a throws keyword just before the return arrow (->). A function which is marked with throws keyword is called a throwing function.

 

Following are syntaxes of defining a function with or without throws keyword.

 

func functioncanThrowError() throws -> String

 

func functioncannotThrowError() -> String

Following is the example of defining a function with throws keyword to throw an exception when invalid parameters sent in function. 

 

enum UserError :  Error {

case InvalidId

case InvalidName

}

func userdetails(id : Int, name: String) throws

{

if id == 0 {

throw UserError.InvalidId

}

if name == "" {

throw UserError.InvalidName

}

}

try userdetails(id: 0, name: "Suresh")

If you observe above example we added a custom errors to enumeration and throwing an exceptions when it failed to match certain defined conditions using throw keyword and identifying the places of throwing an error using try keyword.

 

When we run above program in swift playground we will get a result like a shown below

 

fatal error: Error raised at top level: main.UserError.InvalidId

This is how we can handle errors in an application using throw keyword based on our requirements in swift programming language.

Swift Error Handling Using Do-Catch

In swift, we can handle errors using do…catch block of code. If any error occurs in do code block it will check for matched catch block to determine which catch block of code can handle the error.

Syntax of Do-Catch Block

Following is the syntax of defining a do…catch block to handle errors in swift programming language.

 

do {

try expression

statements

} catch pattern 1 {

statements

} catch pattern 2

statements

} catch pattern where condition {

Statements

}

First, in do block the required function or method will be called by using try keyword. If any error occurred while executing the required function or method it will go to catch blocks and executes matched catch block to execute based on the defined conditions.

 

Following is the example of using do..catch blocks to handle errors in application.

 

let stud = ["BTech": "Suresh Dasari", "MD": "Trishika Dasari"]

enum CustomErrors: Error {

case NoName

case NoCourse

}

func UserDetails(names: [String: String]) throws -> String {

guard let check = names["MD"] else {

throw CustomErrors.NoName

}

return check

}

do {

let user = try UserDetails(names: stud)

print("Name: \(user)")

} catch CustomErrors.NoName {

print("Name Not Exists")

} catch CustomErrors.NoCourse {

print("Course Not Exists")

}

If you observe above example we added a custom errors to enumeration and handling an exceptions using do…catch code block and raising matched catch block based on defined conditions.

 

When we run above program in swift playground we will get result like as shown below

 

Name: Trishika Dasari

This is how we can use do…catch blocks in swift programming language to handle errors based on our requirements.

Swift Converting Errors to Optional Values

In swift, we can convert errors into optional value by using try keyword with question mark (?) like try?. If any error occurred while evaluating try? expression, the value of the expression will become a nil.

 

Following is the example of converting errors into optional values by using try? In swift programming language.

 

let stud = ["BTech": "Suresh Dasari", "MD": "Trishika Dasari"]

enum CustomErrors: Error {

case NoName

case NoCourse

}

func UserDetails(names: [String: String]) throws -> String {

guard let check = names["TEST"] else {

throw CustomErrors.NoName

}

return check

}

let user = try?UserDetails(names: stud)

print("Name: \(user)")

If you observe above example we added a custom errors to enumeration and converting function exceptions to optional values using try with question (?) mark (try?).

 

When we run the above program in swift playground we will get a result like as shown below

 

Name: nil

In case if we didn’t use an optional try?, we will get an error in the application.

 

This is how we can convert exceptions into optional values in a swift programming language based on our requirements.

Swift Disabling an Error Propagation

In some situations, we feel better throwing a runtime error instead of throwing a method or function. In those cases, we can use try! before an expression to disable error propagation. During execution, if no error occurred then try! will return the value in case if any error occurred, we will get a runtime error.

 

Following is the example of disabling an error propagation using try! In swift programming language.

 

let stud = ["BTech": "Suresh Dasari", "MD": "Trishika Dasari"]

enum CustomErrors: Error {

case NoName

case NoCourse

}

func UserDetails(names: [String: String]) throws -> String {

guard let check = names["TEST"] else {

throw CustomErrors.NoName

}

return check

}

let user = try! UserDetails(names: stud)

print("Name: \(user)")

If you observe above example we added a custom errors to enumeration and disabling error propagation using try!.

 

When we run above program in swift playground we will get a result like as shown below

 

fatal error: 'try!' expression unexpectedly raised an error:

In case if we didn’t use try! in our application it will throw an error which we defined instead of runtime error.

 

This is how we can disable error propagation in a swift programming language based on our requirements.

Swift Specifying Cleanup Actions

In swift, Defer keyword provides functionality for execution of statements before code is executed and leaves the current block of code. We can use defer statement to check whether our file descriptor is closed and release from memory. Defer statement won't responsible to transfer the flow of program into another statement like break and return, defer works in reverse order its code executed at the end of code.

 

Following is the example of using defer in application to execute code block at the end of statements execution in swift programming language.

 

func Method()  {

print("Message one Executed")

print("Message two Executed")

print("Message three Executed")

defer {

print("deferred block 3 Not Executed")

}

defer {

print("deferred block 2 Not Executed")

}

defer {

print("deferred block 1 Not Executed")

}

print("Message four Executed")

print("Message five Executed")

}

Method()

When we run above program in swift playground we will get result like as shown below

 

Message one Executed

Message two Executed

Message three Executed

Message four Excuted

Message five Excuted

deferred block 1 Not Executed

deferred block 2 Not Executed

deferred block 3 Not Executed

If you observe above example defer keyword code blocks executed at the end of statements.

 

This is how we can specify cleanup actions in swift programming language based on our requirements.