Book Image

iOS Programming Cookbook

Book Image

iOS Programming Cookbook

Overview of this book

Do you want to understand all the facets of iOS programming and build complex iOS apps? Then you have come to the right place. This problem-solution guide will help you to eliminate expensive learning curves and focus on specific issues to make you proficient at tasks and the speed-up time involved. Beginning with some advanced UI components such as Stack Views and UICollectionView, you will gradually move on to building an interface efficiently. You will work through adding gesture recognizer and touch elements on table cells for custom actions. You will work with the Photos framework to access and manipulate photos. You will then prepare your app for multitasking and write responsive and highly efficient apps. Next, you will integrate maps and core location services while making your app more secure through various encryption methods. Finally, you will dive deep into the advanced techniques of implementing notifications while working with memory management and optimizing the performance of your apps. By the end of the book, you will master most of the latest iOS 10 frameworks.
Table of Contents (22 chapters)
iOS Programming Cookbook
Credits
About the Author
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface

Using error handling


In any iOS project, a lot of operations may fail and you have to respond to these errors in your project. Since Swift 2, a new mechanism has been added to the language for responding and dealing with errors in your project. You can now throw and catch errors when you do any operation that may fail for some reason. Suppose, you do some logic to request some data in a JSON format from a remote server and then you save this data in a local database. Can you imagine how many errors may happen for these operations? Connection may fail between your app and the remote server, failing to parse the JSON response, database connection is closed, database file doesn't exist, or another process is writing in database and you have to wait. Recovering from these errors allows you take the appropriate action based on the error type.

Getting ready

Before starting to learn how to handle errors in Swift, you first have to be familiar with how to represent in errors that are going to happen in your program. Swift provides you with a protocol called ErrorType that your errors types should adopt. Then, to represent errors, here comes the role of enumerations to help you. You create a new enum, which lists all error cases, and this enum should conform to the ErrorType protocol. The syntax of using enum with ErrorType will be something like this:

enum DBConnectionError: ErrorType{ 
  case ConnectionClosed 
  case DBNotExist 
  case DBNotWritable 
} 

As we see it's pretty straightforward. You create enum representing the error that conforms to ErrorType protocol, and then list all errors as cases in the enum.

How to do it...

  1. As usual, let's create a new playground named ErrorHandling.

  2. Let's create now a new error type for a function that will sign up a new user in a system:

          enum SignUpUserError: ErrorType{ 
     
            case InvalidFirstOrLastName 
            case InvalidEmail 
            case WeakPassword 
            case PasswordsDontMatch 
          } 
    
  3. Now, create the sign up function that throws errors we made in the previous step, if any:

          func signUpNewUserWithFirstName(firstName: String, lastName: String, email: String, password: String, confirmPassword: String) throws{ 
     
            guard firstName.characters.count> 0 &&lastName.characters.count> 0 else{ 
     
              throw SignUpUserError.InvalidFirstOrLastName 
            } 
     
            guard isValidEmail(email) else{ 
              throw SignUpUserError.InvalidEmail 
            } 
     
            guard password.characters.count> 8 else{ 
              throw SignUpUserError.WeakPassword 
            } 
     
            guard password == confirmPassword else{ 
              throw SignUpUserError.PasswordsDontMatch 
            } 
     
            // Saving logic goes here 
     
            print("Successfully signup user") 
     
            } 
     
            func isValidEmail(email:String) ->Bool { 
     
              let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}" 
              let predicate = NSPredicate(format:"SELF MATCHES %@", emailRegex) 
              return predicate.evaluateWithObject(email) 
            } 
    
  4. Now, let's see how to use the function and catch errors:

           do{ 
             trysignUpNewUserWithFirstName("John", lastName: "Smith", email: "[email protected]", password: "123456789", confirmPassword: "123456789") 
           } 
           catch{ 
             switch error{ 
               case SignUpUserError.InvalidFirstOrLastName: 
                 print("Invalid First name or last name") 
               case SignUpUserError.InvalidEmail: 
                 print("Email is not correct") 
               case SignUpUserError.WeakPassword: 
                 print("Password should be more than 8 characters long") 
               case SignUpUserError.PasswordsDontMatch: 
                 print("Passwords don't match") 
               default: 
                 print(error) 
             } 
           } 
    

How it works...

We started our code example by creating a new error type called SignUpUserError, which conforms to ErrorType protocol. As we see, we listed four errors that may happen while signing up any user in our system, such as invalid first name or last name, invalid e-mail, weak password, and passwords that don't match. So far, so good!

Then, we create a function signUpNewUserWithFirstName, which takes user input values, and as we can see, we have marked it with the throws keyword. The keyword throws says that this function may throw an error anytime during execution, so you be prepared to catch errors thrown by this method.

Inside the implementation of the function, you will see a list of guard statements that checks for user input; if any of these guard statements returned false, the code of else statement will be called. The statement throw is used to stop execution of this method and throw the appropriate error based on the checking made.

Catching errors is pretty easy; to call a function that throws error, you have to call it inside the do-catch block. After the do statement, use the try keyword and call your function. If any error happens while executing your method, the block of code inside the catch statement will be called with a given parameter called error that represents the error. We've created a switch statement that checks the type of error and prints a user-friendly statement based on the error type.

There's more...

The information that we previously presented is enough for you to deal with error handling, but still there are a couple of things considered important to be known.

Multiple catch statements

In the preceding example, you will notice that we've created a catch statement, and inside, we used a switch statement to cover all cases of error. This is a correct way, but for your reference, we have another way to do this. Consider the following:

catch SignUpUserError.InvalidFirstOrLastName{ 
 
} 
catch SignUpUserError.InvalidEmail{ 
 
} 
catch SignUpUserError.WeakPassword{ 
 
} 
catch SignUpUserError.PasswordsDontMatch{ 
 
} 

After the do statement, you can list catch statement with the type of error that this statement will catch. Using this method has a condition that the catch statements should be exhaustive, which means it should cover all types of errors.

Disable error propagation

Functions that usually throw an error, in some cases, don't throw an error. In some cases, you may know that calling a function like these with some kind of parameters will never throw an error. In that case, Swift gives you an option to disable error propagation via calling this method with try! instead of try. Calling throwing functions via try! will disable error propagation, and if an error is thrown in that case, you will get a runtime error. So, it's better to take care while using try!.