Error Handling | Swift 5, Xcode 10

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on everybody it's your boy kilo loco and today we're gonna be going over oh yeah so what we're gonna be doing is we're gonna be using this app that we see right here and this is going to represent all the different types of errors that we can experience I mean there are a couple of different other use cases that you can obviously run into but for the most part this is gonna cover everything you need to know in regards to error handling so we have four buttons right here we have this X which is gonna represent trapping this question mark that's gonna represent handling optionals this is going to represent networking this little satellite and then the disc the floppy disk is going to represent saving what happens if we were to run into an error while we're trying to save or something like that and I'm gonna get into that as we go it's gonna make more sense as we go but these are just gonna represent the different types of errors that we're gonna be working with now before I get into that I just want to say make sure you head over to Kela logo com give it a check out see if the all-access membership is gonna be something good for you you know if you have any questions about code you can always reach out to me on slack if you're a member so it seems to be pretty effective for a lot of people all right now let's jump into the actual code let's see what's going on and if you want the starter project and the finished project link will be in the description you could download those for free so let's go ahead and take a look at what's going on real quick now we actually have this view controller we're gonna be doing we're gonna be handling the errors in the view controller but we're not gonna be at essentially causing the errors to happen in the view controller well not all of them anyway so what you'll see here is that this is just to make the status bar right but what we see is we have an alert service so this is gonna essentially be the little pop-up that comes up whenever we run into an error or something and then we have a persistent service and a networking service now these are just gonna represent two different types of you know functionalities that you might be dealing with and how they might throw error or how they might cause errors in your app and how you might end up handling them so it doesn't necessarily need to be persistent or networking these are just gonna be examples of different utilities or software's that you use inside of your app that might give you errors and I'm gonna show you how to handle them in different cases so as you can see we have four different buttons or actions that we're gonna be running through and then let's take a look at the networking service just to show you that there's nothing in here and then the persistent service once again nothing in there so just very simple and straightforward alright so let's jump into the first way to handle errors and that's actually called trapping trapping is essentially forcing your app to crash you're like saying hey I don't want to live right now I'm gonna blow up my app so the way that we trap is we just it's it's essentially a one-liner and you probably seen it before and we just type in fatal error all right so if you want this is all you this if you if you want that's all you have to do really to do a trap it's just a fatal error now a fatal error is a function that's like I said it's just gonna crash your app we tap on that that trap and bam it's gonna take us right here it's gonna say hey you blew up you're dead you lose right so that's what trapping is now there are certain situations where you do want to trap and you do want to cause your app to crash because there is a valid reason behind it and if you have a valid reason and only a developer would see this in the like they would only have access to this information in the codebase if this was a regular app all what the only thing that would happen is that the app would crash and then it would just disappear it would no longer be showing on the screen anyway the fatal error you could put it in a message right here saying like don't be doing that cheese man and then if you run it it's gonna essentially do the same behavior there's not going to be any pop ups or anything like that that happened on the screen but if this happens to the developer they'll actually be able to see hey there's a fatal error right here and then you put in a message right here maybe explaining why it's it's a fatal error why you want it to crash that app so that's the first case obviously not the best thing to do you don't want your app to be crashing if you know 99% of the time you don't want your app to be crashing it's only the 1% where you want the app to crash alright the next thing that we want to do is we want to actually handle optional values so let's go ahead and set up an optional case that we can check against to see whether it is it has like a value or if it's new alright so as you can see right here all I'm doing is I'm creating a constant called value and it's gonna be an optional type NE and I'm just immediately setting it to nil so we do know that the value is nil we do know that this guard statement is gonna fail and we do know that we're not going to be able to print this unwrapped value if I were to set it to something that like true we would actually see that yes it does have a value and it would print out the unwrapped value so let's let's go through the case where it works first and then let's go back and find out what happens when we set it to nil so this is the optional we're gonna run this and when we go back over to our our X code we can see in the debug area that it does say true so obviously it's just printing out the value that's right here we're just unwrapping that value now let's go ahead and set it to nil once again and let's run it and see what happens all right so we hit the question mark and nothing happens inside the app but you'll actually notice that the unwrapped value never got printed out as we would expect because it's set to nil so what's actually happening is this code inside of the else statement is being ran and we're just simply saying return so we're actually not giving it any functionality we're just saying return stop right here leave this function and then go on about your business essentially so what we want to do is instead of just returning we want to we want to handle this error like this is unexpected behavior in our in our code so the way that one way that we can handle this is to say to have an alert pop-up saying maybe go back and fix your value so let's go ahead and add an alert that's going to be presented right here if the value is nil all right so as you can see all I did was I opened up this else statement I put it on multiple lines instead of just doing the return I'm actually running some code in here before that return statement so what I'm doing is I'm creating alert from our alert service and if you want to take a look at that real quick you just see that we're passing it in a message and it's going to return back a UI alert controller so we're creating an alert sending it right here and this is gonna be the message and then what we're gonna do is we're just gonna present that alert to the user and then we'll return we'll leave this function and nothing passed this will actually be ran so let's go ahead and run that one more time all right so now we have our app and if we hit optional since our value is nil we're gonna get this alert that pops up and it's just gonna say you know add a valid value before continuing obviously you could run whatever code that you want and obviously you can use a if statement if it makes more sense like if let unwrap value equals value and then you just run this code and then else you could just do this if that makes more sense for you but we're just gonna use a guard statement right here but that's pretty much it for handling optional values you know it's either going to have a value or it's not and if it's not maybe just run some code to you know let the user know or you know run some type of different functionality since it doesn't have a valid value right so that's handling optionals that's error handling with optionals not necessarily errors but you know something didn't go right in our functionality and we're handling it all right so the next thing that we want to do is we actually want to do like like actual error handling like we're actually working with an error and we're gonna be you know doing different things with it we're gonna actually be handling it running logic based off of it so that's where the did tab networking comes in we're gonna be writing code in our networking service just to represent you know a bad use case so let's jump over to our networking service and let's go ahead and add in a function that's essentially called make requests and we're just gonna set this up with a couple of different cases that are going to allow us to you know toggle between having it be successful and failing and there's not gonna be any real networking code in here this is just an example of what might happen in your networking service alright so now that we have this make request function as you can see right here this is just an example of how your networking request might like the the idea of how it might be structured like it's going to try to create like we're gonna check is this a successful request can we actually make this a request and right now I have it set to fall so this is just a boolean and we're saying if it is a successful request which we could just change this to true then we're gonna run some more code and we're gonna check is this a valid response you know right now once again just set to false but if it is then we're gonna just run some some code that's gonna say yes this was a successful response now if if either of these are false which they currently are and we're gonna go over that so if is successful request false what we're gonna do is we're actually going to handle the completion Handler with an error and the same thing goes for if is valid response now I I haven't mentioned this result right here which you might not have seen before but this is actually new to Swift five if you are currently running Swift for or anything below that and you want to kind of copy it or follow along and you don't have Swift five available to you right now what you could do is you could create your own result and you can just do it by doing this alright so all you have to do is just type out you want to call it something well you could call it result since you don't have access to the result from Swift five but I'm just gonna call mine my result if if I were to switch it out and just so that there's no conflicts that is and anyways you're gonna have a result it's gonna be 18 um it's gonna take in 1 it's gonna take in some type right here which if it's successful if the if we do get a successful response we're gonna pass that in right there as a success we're gonna pass that value through if it's if it's a failure then we're gonna pass in E which is gonna be of type error which you can see right here and that will essentially give you the same structure as the result that's provided to you in Swift v now all I would have to do is just change it to this and everything's gonna work the same so if you don't have access to the result from Swift v then just go ahead and do this but I do have access to it so I'm just gonna comment this out and I'm gonna use the regular result also if you need more clear for QK more clarification on this topic let me know and I might even make a dedicated video to it anyway what we're gonna do is we're trying to see is this a successful request and obviously we're just setting that to false no it's not going to be a successful request so this if statement is going to fail therefore we're gonna end up down here in this else block and what we want to do is we want to throw an error so since we're in a specific networking service I don't want to just throw a generic error I want to have a error that's kind of tailored to networking or that's more specific to my networking service so what I'll do down here is I'm gonna create a new enum and it's gonna be our own custom error so let's do that now alright so as you can see down here we have our own networking error and you could feel free to put this in another file if you want to do whatever you want anyway we have our own networking error right here and it's an enum so we're gonna do it on cases and also worse we're conforming to the error protocol which means that will actually be it'll be able to throw our networking error whenever we want to or pass it as an error if we wanted to so what we could do is we could say we could finish up our completion by passing through a failure Kay I'm sorry a failure case and pass in invalid so let's see what that looks like right now all right so as you can see we we're passing through our completion we're saying that it's going to be a failure our result is a failure and we're actually going to throw this error or we're gonna pass through this invalid request error now since this is a networking service and we have a networking error that's going to essentially handle all the errors in our networking service what I'll actually do is I'll change this to a networking error this way I know that I'm always going to be getting back a networking error whenever it's coming from this specific function right here so I know that I will always get back a networking error so now we no longer have to specify that it is a networking error because we know that it's obviously a networking error right here so all we have to do is just say dot invalid request so let's go ahead and see what that looks like if we jump back over to the view controller and we go ahead and use our networking service to make a request so let's do that all right so before I go any further I just want to show you what it's going to look like when we actually do this so what we're gonna do is we're gonna call make request and then this parts gonna highlight and since it's a completion Handler with a closure that's passing in our result so what we need to do is we need to hit enter that's going to change the format of the closure and then what we need to do is we need to say that this is actually a result we'll call this result you can call whatever you want but I'm gonna call it result because that's clear then since this is a result which is technically a enum remember look back up over here it is a enum the the swift one is a enum as well we would switch on it so let's call a switch statement for both success and failure all right so before we move any further I just want to make sure that it's clear that a result type has as we can see a result type has a success case and a failure case and they're both popping they're both passing values through on these enums and this one is gonna be whatever it doesn't matter and then the e the failure will always be an error so what we can do is we could just say let message we could call a message we'll pass a string on the other side right now and we could just print out that message if we wanted here this one we know is going to be an error so I'll just call it let error and since we're dealing with an error what I want to do is I actually want to once again print that in an alert so let's go ahead and add that functionality right here and create an alert and then display it to the user using our alert service alright so this is essentially what we're gonna do but remember since we are inside of a closure we want to make sure that we do have a weak reference to self and whenever we access one of our instance properties we want to make sure that it is calling the the weak reference to self so once again what we'll do here is we're going to have our alert service and let me just unwrap this alright so once again that as you see right here we're grabbing we're grabbing an alert from the our alert service which creates an alert from a message now a error always has a localized description whether it's implemented or not that is that is up to you so if we were to run this right now I want to show you what happens alright so now we're gonna hit the networking we're gonna call this and this is actually what the localized description looks like by default it says the operation couldn't be completed and then it passes in some garbage that you're usually should never see because nobody I don't even know what that says right so what we want to do is we want to make sure that our error has a localized description so what I'll do is I'll go back over to my networking service because that's where I have my networking error at and what we're gonna do is we're going to add an extension to our networking our networking error so we'll say extension now in this extent what we want to do is we want to make sure that it conforms to localized error localized error has a error description on it which will allow this which will essentially allow us to pass the localized error that we're trying to present over here or the localized description over here whenever we say localized description for this specific type of error so what I'm gonna do is I'm just gonna modify the error description property but I don't want to have to do a switch statement based off of all the different types of errors that we're gonna have in here because let's say we had fifty different you know cases for our networking error that's gonna be 50 different cases that we're gonna have to switch on if we were to make it you know to switch based off of those so what I'm gonna do is I'm also gonna make my networking error conform to the string protocol and that's going to allow me to set the invalid request case to string value so then what I can do is I could write in a message right here alright so now we have our invalid request that actually has a value of you have made an invalid request foe and what we're gonna do is we're just going to simply return NS localized localized NS localized string this one right here and we're gonna initialize with the key the key is actually going to be the raw value which is essentially whatever this string value is right here and then the comment we're just gonna leave empty because we don't need a comment to go with it so now that networking error conforms to the string protocol and the error protocol invalid request has a value like this and it's also the networking error is also conforming to the net of the localized error we're actually going to be able to return an error description or a localized description which we're getting right here so we haven't changed anything over here and now when we run it and we tap on the networking we're gonna see you have made an invalid request though so that's just um you know working with custom errors and formatting them special ways and you know now that it has localized description whenever we pass this errand if we don't know what kind of error to expect this error will actually be managed properly because it will already have a localized description because we set it up to be that way so let's continue we're gonna go back up to our networking request and we're gonna see what happens in this case so let's say it is a successful request right so now we have to go through some other logic that have to check if the response is actually successful well we don't want to pass in an invalid request we want to actually pass or we don't want to say oh no it's not an invalid request because it is a valid request because we got that far what we want to do is we want to say no this is an invalid response so let's go down here and add in our networking error we're just going to add a new case alright so as you can see down here in the networking error I'm throwing I have this new case which is invalid response and now it has this new string for the value so now since it once again it's a networking error which conforms to localized error this is going to be the new error description for this specific case so what we can do is if this is not a valid response we can just go ahead and run similar code to this so completion failure invalid response and remember that the only reason why the syntax is like this and I don't have to have networking error before invalid response is simply because we know that it will always be a networking error so let's go ahead and run this again and see what is what's popping up now alright so we go and there was something wrong with the response that came back so now we know that we made it this far and this kind of gives us an idea of what's going on in the code because if you're trying to debug you might have very similar messages to the user but at least you'll know hey where am i gay this message where am I getting this message that says there was something wrong with the response you'll be like okay well I need to look at where invalid response is at and then I could do command F and I could be like okay where am i calling invalid response right and then you can see right here oh okay well something oh this is what the area that something happened I need to look right here to do my debugging and fix my app so this is the benefit of having these different types of errors because not only can we display different information to the user but it can also help us debug exactly where the problem is happening in the code so lastly all we want to do is we just want to say true and we're just going to you know finish this off by saying our completion is going to be finally a success all right and remember on the other side in our viewcontroller that if we do get a successful response we're expecting it to kind of be a string we're gonna call it a message and we're just saying yay came back as a it came back right not came back it came back boy and we go back over to our view controller and now we're gonna actually see that this code is going to be running as opposed to this code that's been running the entire time and we're just gonna print out that message or we could put in our alert service or whatever we want it to do there we go since it's coming back as a string we just had to create an alert for it just like we did for the error and now instead of checking the logs we can see yay it came back right all right awesome hell yeah okay so we're almost through with error handling and that I know it's a lot of information but I mean it is kind of overlapping subjects so that's why it's taking a little bit longer for me to cover all this stuff anyway the last thing that we want to do is we want to handle when somebody taps on save now let's go into our persistence service and let's go ahead and write out some you know some flags or bullying's like how we did in our networking service that are going to give us false and we're going to go through each of those step-by-step as well all right so this is our persistence service it only has a function on it called save and this save is a throwing function now I'm going to talk about what throwing is right now but let's just take a look at what's inside of here so we have three different flags one is is new topic so I'm just assuming this is just a new topic for you you never heard about it and you know every time you implement something something the first time it always seems to crash right and then then we have another flag is valid context and then we have a different flag that says can write to disk so obviously we're just setting all of these to false so that we can go through each of them individually and see how they're causing errors now if we have all of them set to true we're gonna make it all the way to the very end and we're actually going to have saved successfully when we'll just print that out but if we don't then what we're gonna be doing is we're gonna be throwing these errors so remember that I said that this function throws that means that instead of you know just returning or being able to run this function and then continue you actually need to handle this with a try so I'm gonna go over the tries and the view controllers but let's take a look at what's being thrown real quick now is this a new topic and you know like I said this is just gonna be something that's gonna just randomly crash on you because you didn't set it up the first time or something that like that right well in this case this would happen from like maybe your framework or the technology that you're working with and it's going to crash on you and this wouldn't be one of your errors it's just gonna crash on you so right here I'm just gonna represent that that you know SDK crashing on you with this NS error and as you can see this is an actual error type it's not just the regular error where it's a protocol and we're just gonna say oopsy and then it's gonna have a code eight zero zero eight five and then we're not passing any user info if that isn't going to cause us to throw an error what's going to happen is we're gonna check is this a valid context in this case we're actually writing in our own code let's imagine right and we'll throw a persistence error and we'll just say invalid context lastly if we can't write to disk we're gonna throw a persistence era and we fail to write to disk now notice that there's nothing to specify what kind of error is going to be thrown so that's why we're able to throw a NS error like this and persistence error like this because there are all types of errors that can be thrown it's not being limited to only persistent persistence errors being thrown now let's go back over to our view controller and in our did tap save we're gonna we're gonna try to save we're gonna try to call save on our persistence service and the first time we're gonna get this error so what we want to do is we want to handle this and I'm gonna handle this in a couple of different ways first we need to go over how try works so let's go ahead and create a couple of different functions that are gonna represent the ways that you can handle try alright so I have these three different functions which are gonna represent the different ways to handle try first we're gonna do it with the force but what we want to do is we want to try to we're gonna run one of these saves which is essentially going to just call our persistent service and save it but it's going to use different types of try all right so before we actually go into trying to call each of these and actually implementing the functions where they're gonna be used in this did tap save up here what I want to do is I want to go over how these are actually working so a force try this is going to force this to happen so you're like essentially saying I guarantee this is gonna work this would never crash not never not never so if something goes wrong obviously it's going to crash so let's go ahead and try that right now and we're gonna call Force Save and what we want to do is we want to see if some functionality is happening after we call this force Save so let's say down here now let's go ahead and run this and I want to show you what happens when something goes wrong and you force try alright so remember that we're going to do the save and when we tap on it what's going to happen is since we're forcing it where we're unwrapping a sense it's essentially unwrapping an optional kind of right so we're forcing that to happen and it's actually crashing it's blowing up our app so not only is it crashing but obviously any code after that crash is not going to run so we never got this yay we are going to do some other coding stuff so that's never being logged down here right alright so moving on to the next thing what we want to do is we're gonna just go ahead and calm out for comment out for save and we're just gonna say attempt save now as you can see this is with an optional this is an optional try which means go ahead and try to do this but if it doesn't happen then just keep moving on we don't really care so let's go ahead and run this and let's see what happens all right so we hit the Save button and notice nothing's happening in the app I could still do other stuff but if I go back over here and since I've tapped it three times you're actually gonna see that yay we are going to do some other coding stuff now if it was important that that the save actually happened before we move forward then this would be a problem right here because we used an optional try and that's essentially saying that hey you know what worry we don't care if it works or not just go ahead and keep running the code after that this is not really you know important so that's what happens if we use a question mark after the try now the proper way of actually handling you know functions that throw which our save function throws is to put it in a do catch block and as you can see here we're right we're wrapping in a Duke in a do block so we're gonna try to save on our persistence service but if that doesn't happen what's going to actually happen is catch is gonna be called and catch is always given an error so catch actually looks like this behind the scenes this is catch let error and that's where you're getting this error from but we don't have to explicitly say that so or type that so we're automatically given an error that's spelled exactly like that and what we can do is we can set this alert variable that we have up here to this alert that we're creating with this localized description and then if this is a true value and we can unwrap it we're just gonna present that alert so let's go ahead and run that now when we hit the save what's going to happen oh well we have to make sure that we're calling it let's make sure we call it so we're gonna do handle save properly in the did tap save let's run that one more time all right so now when we tap on the save but but and what's going to happen is we're gonna get the operation couldn't be completed oopsie error 8000 or 80 or whatever the hell that number is right so we're actually getting an error and we're getting the localized description of that error now remember that error is that that description is actually coming from over here in our persistence service where we created that NS error right so what we can do is we can well we wouldn't actually have access to this error remember this is supposed to represent an error that you don't have control over but if we wanted we don't you could just say hey you know what the SDK crashed we don't have to specifically say error right here so let's go ahead and change that up right so now whenever we hit an error we're just gonna say the SDK crashed on us so let's go ahead and run this again in our handle save properly and we run that and it says the SDK crashed on us which is true because we're actually getting that error that we got now also keep in mind that this is saying yay we are going to do some other coding stuff down here now depending on what you want maybe you want to handle you want to have whatever functionality is gonna happen down here you could put it in your do block there's a couple of different ways that you might want to handle that it just depends on what you're trying to accomplish but as you can see we're handling the safe properly but it's still gonna move forward kind of like it did when we did the attempt save the question the the one with the question work but we're just catching the error and we're presenting it in the UI now let's go back over to our persistent service we're gonna say that we're gonna set this one to true and what's going to happen is now we should be getting an invalid context error so let's go ahead and run that and let's see what happens all right so we're gonna hit save and it says the SDK crashed on us which isn't actually the case what's actually the case is that we have an invalid context and we're actually passing in we're passing in this error so we would actually know that if we checked but we're not checking all we're doing back over here in our view controller is we're just automatically assuming anything any time this function fails for whatever reason we're just running this code regardless of what happened so we don't want that we want specialized error handling we want to you know do different things in different cases so what I can do is I can change up this catch block and make it so that it's catching specific errors so now what we have is we're catching this specific error so that we can check any type of error if I I could even put this as a networking error but that wouldn't make sense in this specific context but we can put any error right here and we can check if it's this specific error and we can we can run different functionality based off of if it's this specific error all right so as you can see I'm just gonna represent you know different code or different functionality by entering in a different message right here so if we go ahead and run this now and we hit save we're actually going to see there is something wrong with the context we know that fix the context and it's and we know that because it's this specific error now if I go ahead and go back once again to my persistent service say that this is a valid context we're just gonna say true and we're gonna run this kin right to disk and we're gonna obviously hit this this error right here which is the failed right to disk and we run this once again we get SDK crashed and that's because as I stated earlier in the view controller this is caching everything that hasn't been caught already so we're catching them in this specific order we're checking if it's invalid a persistence error invalid context if it's not then we're just anything else that's outside of that specific error we're just gonna throw this functionality out out at it so we don't want that we want to check if it's a write to disk error so let's go ahead and add that functionality in - all right so if we fail to write to disk if it's a persistence error fail to write to disk then we can run this specific functionality and what will happen is we'll actually get an alert like so so let's run that one more time and if we go ahead and hit save you can see that could not write to disk maybe you don't have enough space on the hard drive so now we're giving specific feedback for specific situations on what's going on inside of our app why there's errors popping up and what the user what action the user might want to take after that so and then the very last thing is just to make sure that what happens when all of this works and remember at all this time we're still getting that yay go do some other coding stuff right and then if we just set all these to true none of these errors are gonna be thrown and what's going to happen is nothing's going to actually happen visually in the Hat that's when your main functionality would happen but we would get we saved successfully which we're getting right here and then we're running this code right here that says yay we are gonna go do some other coding stuff now down here so that's error handling I don't want to ramble out the end of this just if you if you found this video valuable just make sure that you share it with as many people as you can it really helps the channel and make sure you go out there and keep coding passionately you
Info
Channel: Kilo Loco
Views: 7,238
Rating: undefined out of 5
Keywords: swift alerts, swift uialertcontroller, swift custom alert, ios custom alert, swift alert storyboard, swift helper service, swift best practices, swift toast message, swift pop up, swift error alert, swift notification, how to handle alerts in swift, whats new in swift 5, swift error handling, swift custom errors, swift localized error, swift error description, swift result enum
Id: fhcINdzuq4A
Channel Id: undefined
Length: 38min 10sec (2290 seconds)
Published: Fri Feb 15 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.