When to use error handling

The three distinct error-handling patterns that we saw in this chapter were:

Now that we have explored these three error-handling patterns, we need to decide when to use each one. In order to help us understand which error-handling pattern to use, we need to really understand the advantages and disadvantages of each.

Error handling with return values is definitely the easiest error-handling pattern to implement. In this pattern, the value that is returned from a method or function indicates whether we had an error or not. This return value could be something as simple as a Boolean true value (indicating success) or a false value (indicating failure). The return value could also be something more complex, such as an enumeration whose values would indicate specific success or failure conditions.

Handling errors with the NSError pattern is the most complex because we need to deal with the complexities of the NSError class. Once we get use to using the NSError class, it really is not that bad; however, compared to the other two patterns it still adds additional complexity.

Error handling with the do-catch block is the error-handling pattern that was introduced with Swift 2. This pattern is very easy to use but it does add additional complexity that is sometimes not needed when we simply want to know if a function was successful or not.

It is very easy to ignore errors when we use the return values and NSError patterns for handling errors since the returning code is responsible for specifically checking for the errors. If we use these patterns, we need to make sure that we check the return value and respond to any error that may occur.

Let's look at a couple of examples to see when we should use each error-handling pattern. In this first example, let's say that we have a function that checks to see what type of network connection we have. Our return values would be an enumeration that could contain the following values: WIFI, MOBILE, or NONETWORK. In this function, if an error occurs while checking the network connection, we would generally want to set the network type to NONETWORK and have our code assume that there is no network connection. This would be a great candidate for handling errors with return values.

In this example, if we do need additional information about the errors that occurred, we could add additional enumeration values. We could also throw the error using the do-catch block; however that may be an overkill if our code simply treats any error with the network check as not having a network connection.

For our next example, let's assume that we have a function that retrieves values from a data source (a Web Service or database). Simply returning a nil value to indicate that our data source is not available may not be enough because we would also return a nil value if no value was found. In this example, we should use the new error-handling pattern that was introduced with Swift 2. This will allow us to return a nil value if the value was not found or throw an error to let the code know that the data source is not available. Our code would probably want to treat these two conditions separately.

In reality, the only time we should use the NSError pattern for handling errors is if we are planning to create a framework that may be used by applications that do not support Swift 2 or may be used with Objective-C.