iOS Development Tips Weekly

– [Instructor] There’s many ways to handle errors in Swift, for some errors, using throws is a great way to handle errors without crashing the system. Download the exercise file and you’ll find a project with an embedded playground. Go into the playground and we can close everything else up to make it all nice and clean and easy to read and you’ll see, we have a small program here that, while there’s a lot better ways to do this, I’m going to use an example of a function called coffee that finds the rating of a type of coffee using two arrays. You’ll notice that there’s some Index Out of Range errors possible here in the rating and the search. We have five elements in coffees and only four in ratings, so this Kona element is going to give us an error, we’ve got a negative one here in the ratings and you’ll notice that we have a rating down here for count, using the string repeating and that’ll give an error, so we got plenty of errors and the Error Not Found for the coffees, that’ll give us a null value that’ll blow away this explicit wrap here. So we’ve got lots of things that can cause errors and we can go ahead and try that. I’m going to change this to Kona, for an example, and run and you see we get an error. I can change this to Java and run and we get an error. For internal fatal errors of a function we can use throws. To use throws, what you’re going to do is go up to where it says coffee and just before we return the value, and after the parameter, put in throws, like that and that tells you that this is a throw function and you can see already that it’s complaining down here on my print statement. Now let’s go take care of one other piece of work we have to do before we start doing things in our function. You’re going to need to identify the error when you throw it, I’m going to use enum that adopts the error protocol to do that, I’m going to add three errors. Let’s start this by doing enum CoffeeError and it has to adopt error, like that. And now, once you’ve done that, you’re going to make some cases and my first case is going to be coffeeNotFound, my second case, I’m going to do something funky with this and I’m going to do ratingNotFound and I’ll put in here another value. You can send back values in your errors as well and I’m going to show you how to do that. And finally, we’ll just do badRating, that’s for that negative one case that we have. What I’m going to do here, let’s give myself a little more space for the moment, is I’m going to use those errors in my method. Now my first error is in a nil index, which I’m going to use a guard for, so I’m going to change this let ratingIndex = index! to, first of all, guard and then, I don’t need that exclamation point anymore, but I do want to put else, to handle the situation that I’m going to do. And the way you use throws is you’re going to put throw and the error and so, I’m going to do CoffeeError and then I’ll pick my coffee error, in this case, it’s the coffeeNotFound and so, that’ll take away my nil error that I’m getting from this index here. My next error has to do with the rating index and for this one, what I’ll do is just check to make sure I don’t overflow and so, I’m going to do, if ratingIndex >= ratings.count, if that’s the case, then I’m going to get in, I’m going to throw another error and that one’s the ratingNotFound error and you see we’ve got that string there that we can put in there and so, I’m going to put in name, so it’ll go back and give me my name of what caused the error in the first place. And the last one I want to do is, I’ve got the rating made, let’s go one step below that and I want to make sure that this is not less than zero and if I have an error with less than zero, I’m going to get a bad rating, which would cause this to have an error and so, I’m going to prevent that using a throw here, throw CoffeeError.badRating. So if you’ve made your own thrown errors, that’s how you’d set them up. Now more than likely, you’ll be handling the error and just like we have down here. You might set one up like this, but there are a lot of factory methods that throw errors, the standard way of handling throw errors at the do/try/catch construct. I’m going to comment this out for the moment and head up here over this error and put the word do and then, inside the do, we’re going to put a try, which just says, okay, I’m going to be doing something with throws in it and then, what I’m going to do is I’ll just copy what I have here and paste it in. Now that’s not the whole story, because underneath this I got to deal with the error case and so, what I’m going to do for that is just do a catch and that catches your error and we can just do something simple like print. And that would be the simplest version of a do/try/catch is do, try and then you put the statement, this is always first in the statement, then you put the statement that has the thing that’s getting thrown and if there’s an error that the thrown catches, you put it down here. You can get fancier with this and that’s one of the real powers of this, I’m going to give a couple more lines here, I’ll put another catch here. You can have more than one catch on a do and the nice thing about that is you can take your errors and handle them if it’s a specific error. So for example, catch CoffeeError.coffeeNotFound and I can actually print a message, myCoffee not found. I can do something similar to that with the rating not found and what I’ll do at the end of here is because I’ve got that parameter that I stuck on the end of it, I’m going to do let coffee, and that lets me use, inside the catch, that value. So I can actually do print coffee does not have a rating and then I can use the general catch here, which’ll catch my bad ratings and I’ll just say error for that and that could be for all my other catchalls, I could of course put a bad rating in here. So we can go ahead and run this now and it tells you Java’s not found. I can change this to Kona and it says Kona does not have rating and we have the dark energy, you have this negative one here, so let’s try that one, go ahead and run that, then I get an error and that’s because I made a little booboo here if you look up here in the code. You do want to make sure you’re looking for the correct condition here and that should be rating, not rating index, run it again and I just get my simple error. Now that’s one way to do this. Another way to do this is you can use a nil value instead of do/try/catch and that, you use a try with a question mark on it, so you can do things like this, where you’re just looking for a nil case. So I can do if let coffeeRating = try? and then put coffee myCoffee and I can print my rating and change this to coffeeRating. Else, we’ll just print Error, and you can do that as well. There’s one other case you can do and that’s in the case where you don’t even check for anything, so let’s change this to Sumatra for example. I know Sumatra’s going to work, everything in my code says it will work, if it works, something is horribly wrong, so in those cases, where you have things like that, it’s very common, for example, if you’re loading files that you know the name of, that you’ve explicitly given a name for, those kinds of situations, you’re going to use a different one called try, it’s kind of living dangerously, but if you’re absolutely sure, you can just put a try like this and it just ignores all of the catch-type stuff you need to worry about here. I can run this and you can see that that works fine, I’ve still got my errors here, so if I go up here, I’ll actually do that to Kona, run again and you see it says, Kona doesn’t have a rating, we get the error for the nil case and we got our actual Sumatra here. Now the best way to handle an error is not to make one, however, when creating methods in classes, you will find places there are errors you can’t control, throwing errors will notify any other classes and methods that there is trouble.

Leave a Reply