Download JSON from API in Swift w/ URLSession and escaping closures | Continued Learning #22

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right welcome back everyone i'm nick this is swiffle thinking and i hope you guys are now excited for this video because we're gonna finally download some data from the internet and we've been building up to this for a couple videos now and if you haven't watched my last couple videos i recommend watching those first because we are going to use a lot of what we learned in this video and that includes using background threads using escape enclosures and of course using the codeable protocol to convert our web data into data that we can use in our app and i do want to mention that we're going to use a free public api to download some just fake test data into our app and i'll show you that api as we get into the code but if for some reason that ever gets shut down and that website gets turned off i will post a replacement api in the comments below so with that said i hope you guys are excited because downloading data from the internet into your app is something that is obviously super important and used all the time so let's finally jump into our xcode project and download some data convert that into something usable and let's put that on the screen so we can actually use it in our app all right welcome back everyone exciting video today because we're going to actually download some data from the internet this is what we've been building up to in the last couple videos and you're gonna start to see why i covered everything that i previously covered uh before this so that we can really hit the ground running in this video so let's right click the navigator create a new file this will be a swift ui view and i'm going to call this download with escaping bootcamp i'm calling it download with escaping because i'm going to do another video probably next uh which we're going to download with something called combine which is a new framework from apple but right now we're just going to download with escaping which i previously covered in this course i think two videos prior so download with escaping boot camp go ahead and click create once you're inside click resume on the canvas and let's get coding and we're going to start off very simply as we always do by creating a view model let's call this class download with escaping view model so we can conform to observable object open the brackets escaping and let's initialize one in our view so we'll use an at state object var vm for viewmodel and we'll set it equal to download with escaping view model all right and in our view model we are going to create an init and then we're going to create a function called get posts open close parentheses open the brackets and in this get post we're gonna actually download some posts from the internet so to do that we use something called a url session and we'll do dot shared dot a data task and we are not going to use the one with the publisher so just a regular data task and we're looking for one with a url and a completion handler so down here url and a completion handler and of course we need a url this is where we're going to download that information from so let's comment this out because we don't have a url yet we'll first say let url equals url and we'll open the parentheses and use the string here and we don't have our url string so let's just leave it a blank string for a second and then we can take this url and pass it into our completion but of course when we when we create a url like this it is optional so to unwrap it we're going to use a guard let statement so we'll make sure we get this url else we will return and we know this will never fail because we're going to put our url directly in here so we'll have this url and then we have a completion handler we can press enter on this and we can see that we get some optional values back we might get some data a response and possibly an error so let's call this data let's call this response and let's call this error and with this one simple line of code here we are going to that url whatever that url is and we're going to download whatever is at that url and then once it comes back with all that download information this closure will run with possibly data response and error so the first thing we want to do before we use anything is check that we have data check there's a good response and check there is no error but before we do that let's actually at the bottom of this task here let's call dot resume so this sets up the task but it doesn't actually start until we call resume so this is kind of like the start function and it's resumed because you can pause or suspend a task and then resume it again but we're just going to use resume basically to start it so in this code here in this block let's first check that we do have data we'll say guard let data equals data else and if there's no data we will print uh no data and then we can return let's check that we have no error we'll say guard error is equal to nil else we will print error and we'll do a colon backslash open close parentheses and here we can print out uh the error we're going to get a quick message here that the string interpolation produces a debug description we can just click fix on this to silence the warning and then we will return and then we get this response and we want to make sure that this is a http url response so we're going to say guard let response equals and i think i spelled response wrong here so response response as with a question mark nhttp url response we'll say else we'll print here uh invalid response then we will return and finally we want to make sure that this response is a good response so if you google http url response codes which i did right here i found a random website basically there are generic codes that are used across the entire internet to determine what type of response it is whether it is informational successful whether it's an error or a server error so we're basically going to make sure that our response is successful and it's between 200 and 299. so down here we'll just say guard uh response dot status code is greater than or equal to 200 and response dot status code is less than 300 else um status code should be 2xx for the 200s comma but is i'll do backslash open close parentheses and we'll print out the response dot status code so we'll know what code we're actually getting back and then we will return again all right and finally after we have all these checks and we know we have good data we can then actually start using it in our app so down here i'm going to print out successfully downloaded data and then i'm going to print out the data and just like in the last video i'm going to convert this data into a string just so we can see it on the console so i'm going to say let jason string equals a string and we'll open the parentheses we'll use the data encoding initializer we'll pass in our data and the encoding will be dot utf-8 then let's just print out the json string okay so there's a lot of setup here that we will shorten in a second but i wanted to walk you through like everything that's really going on in this data task so in our knit let's call get posts and this should then run as soon as we load up the app the final thing here is i want to put a url into our url because we actually need somewhere to download from so what we're going to use is a website called the jsonplaceholder.typeacode.com and this is a public website that's free to use and it basically has a free fake api for testing and prototyping and this is super helpful as developers because it's often much easier to use a fake api like this rather than having to create a fake database where we can download information so i'll put the url to this website in the comments below uh if it for some reason ever gets shut down i will put a replacement in the comments as well but on this website if we scroll down we can see that there are a bunch of resources and it's showing us six common resources here and if we click on posts we can see that this there's a url which which is basically just this web address and this has a bunch of json data for posts so we have user ids a title we have user id an id a title and a body if i go back there are other options as well we can do comments photos the photos actually have a image url where we could download an image from uh there are to do's so like if you wanted to make a to-do list and you can see that each of these have different bits of information that are super helpful when we are creating our application so to start we're gonna scroll down to this route here with the posts backslash one and this very simply is just going to return us uh one single post so we're gonna start with this very simply and i'm just going to come up here and copy this json placeholder url and go back into my app and paste that in here the first thing i want to note is that apple prefers if we use https so i'm going to add the s there and hopefully this will work and if it does we will get this success print out and we can actually see the json string in our console so i'm gonna go so i'm gonna take the view that we set up at the beginning the download with escaping bootcamp and i'm gonna make that the first view in our app so let's open up the navigator go to the app.swift file this is where your app main call is i'm going to paste in that view that we want to be the first view let's make sure my simulator is an iphone 12 and i'm going to click run to build it onto a simulator and jump back into our code as well and as soon as it opens we should get something printing out to the console all right so if nothing printed out for you chances are you did something wrong um but i have a print out here that we successfully downloaded data so the fact that that's printing out shows me that we set up the url and all of these checks passed so we did get data there was no error it was a good response and then we came down to this successfully downloaded data and we can see that the data comes in bytes and the data actually looks a lot like this string here so it's not usable just yet in our app and this is why i'm doing these videos in order because in the last video we focused on the codable protocol and we learned how to decode this data into something that we can actually use in our app so if you don't know what that is go watch the last video in this series it will explain a lot but if you did you are ready to actually decode this real quick and what we're going to do is create a model uh for this data so if i so up above the view model here we're going to create a struct let's call this post model and we'll open the brackets and if i go back to that website i can see that the post model has a user id which looks like an integer an id that looks like an integer a title that's a string and a body that's also a string so all we need to do is set up this model and make it codable and i want to note here that the in user id the i is capitalized and the d is lowercase and we're just going to copy that exactly so back in our code we'll say let user id and this will be of typeint let id of typeint let title of type string and let uh what was it body body of type string all right and because we have an idea ready we can conform to identifiable and because we want to be able to decode and encode this post model from json we're going to make it conform to codable and again this is why i covered codeable in the last video so now that we have this we can actually decode that data um but before we move forward i just want to throw out there that uh sometimes that this was pretty easy to set up because we only had four items here but sometimes this gets super complicated and especially if you're a beginner developer it could get confusing on how to actually set this up correctly and if you don't set this up correctly the coding the decoding and encoding might fail so i'm going to copy this result here and there's actually a website that i use sometimes i want to introduce you guys to and it's app.quicktype.io and on this website we can paste in json data and we can set the language on the right side to swift i'll also put this in the caption below and this website will actually convert the json data into a swift struct for us so and you can play around with some of these customizations sometimes you want to make properties optional so you can click on this optional and everything will be optional and there's some other really cool things here but basically if you get stuck trying to create that model this could be a great solution to figure out you know all of the variables that you do need to set up we don't need it for our purposes so i just want to introduce you guys to it but let's go back into our code here now that we have our post model let's let's decode the data into a post model so in our view model we're going to create a at published var we'll call this posts this will be of type array of post model we'll set it equal to a blank array to start and when we get this data down here let's just say let new post equals we'll say try with a question mark we'll say json decoder open close parentheses dot decode and the type will be a postmodel dot self and data of course will be the data and this post is optional but let's just make sure we get it with a guard let statement we'll do else return and if we get this new post we will call self.posts.append and we'll append a new element with the new post and if you follow my videos a couple videos back we looked into background threads and performing tasks on a background thread and the reason we did that first is because when we use these data tasks it actually goes onto a background thread by default so that's efficient when we're coding because we want to do all that downloading on the background because it's not actually updating the ui but in that video i mentioned a bunch of times that every time we come back and we want to update the ui after being on a background thread we then need to update only from the main thread so when we append this post it's going to update the ui so we need to do it on the main thread so we'll call dispatch queue that mean dot async and we'll put our posts inside and finally this is now creating a strong reference and we can make it weak by using the weak self in and this would then be optional all right now hopefully this post is appending and down in our view let's create a very simple view to put all the posts on the view so we'll create a very simple list open the brackets we'll do a for each and and we're going to loop on the vm dot posts remember posts already conform to identifiable so we can do this click enter on the content and this will be for each post and before each post we'll add a v stack and we'll just have very simple text with the post dot title and a text with the post dot uh body let's just make the title dot font of headline and we'll give the body with a foreground color of gray all right i'm gonna run the simulator one more time and this time hopefully we do append a post uh to our app so it's gonna run and and this is beautiful we are downloading this data from the internet we are converting it from json data into our post model and we're displaying it on the screen so i'm going to hide this hopefully your app now looks like this and you're getting some of this data i'm going to make the alignment on this v stack leading so that it pushes to the left side let's also make the frame max width of infinity and alignment of leading i'm gonna run it one more time just to make sure that that's pushing to the left all right and before we move forward i want to come back up here and take a quick look at our code so we don't need this printout anymore successfully downloaded data i'm just going to delete that and secondly we know all these checks are working so a lot of times people will combine all these checks into one single guard statement so we can so let's do that quickly we'll say guard let data equals data comma we're gonna do error is equal to nil comma let response equals http url response comma and then the status code all right the if if this else fails now this will just be uh maybe error downloading data and we can delete all this extra code so we have our one single little guard statement here which is super handy but one thing i want to point out is that this this bit of code this url session data task is fairly generic we just pass in a url and we get data back and if we had an app where we had a whole bunch of different urls and we kept calling this download task we wouldn't want to have to rewrite this code again and again and again and always checking through our data so it's more efficient to create a single function that is generic that we can use to always download data from any url and check that that data is successful so we're going to create a func down here we'll say funk download data we'll give we'll add a parameter of url and it'll be of type url of course we'll give it an external name of from url and this download data needs to return some data we want to make sure that we do get this data because we're going to need that data here to actually decode so if you're new to swift you're probably thinking we can do a return with some data but if you watch my video i think maybe two videos ago i covered escape enclosures and when we are downloading something that is asynchronous and it takes some time to return back to our app uh we actually need to use an escape enclosure here so this url session is executing immediately but the return is not happening until it actually goes to the database and comes on back so because we can't return immediately we have to use the escape enclosure so let's add one here we'll add a completion handler of type at escaping and this will we're going to open the parentheses use the underscore and this will return data of type data and we'll make it optional and this will return a void and then we will open the brackets so if this bit of code is confusing to you i covered it two videos back when we cover the escape enclosures and that's why i did that video before this because here we're going to focus on downloading data and we're not actually focusing on this escaping um i will note that more commonly than void people will use the open and close parentheses here so now that we have this generic function we can add our code inside so what i'm going to do is copy this whole url session i'm going to paste it inside and i'm going to get rid of this bit of code here and after we do get this data and we know that it is good data we've gotten past this guard statement we're just going to call completion handler and we need to pass in some data so we're going to pass in our data here and it should work and there's one thing that we do need to think about now is that um if we went into this guard statement and we returned out of it so if there was an error and this block was called the completion handler is never being called inside this block and most of the time we want to make sure the completion handler is called whether or not this is successful so that the rest of our code knows that this that this task is finished so inside this block before we return nil we're also going to call completion handler and put in nil all right so if there's an error the handler the data that is returned will be nil if there's no error it will actually be data so now back up in our code so now back up in our code after this url i'm going to call download data from url click enter on the completion and this will be returned data and here we can just check if there actually was returned data so we'll say if let data equals returned data and then we'll do else print no data returned we know this isn't going to happen because this is going to be successful but just for our sake for right now let's let's include that else statement and once we have this data we can then add this bit of code here so our guard statement where we are decoding the data to a post model and then we are appending the post model so i'm going to paste that here going to get rid of this data task i'm going to hit play on the simulator one more time let's reload it make sure our download is still working we are successfully downloading and now we have this generic function which is super powerful because we can use this function across our app a bunch of times for a bunch of different urls uh even if we're not downloading posts if we're downloading something else we can always use this download data because it's going to go to the url and just return us generic data then after we get that data back in our custom function for the posts we will decode it into a post and then append it i hope you guys are with me now and we're going to jump back onto that website the jsonplaceholder type of code.com i'm going to go to the backslash posts and here we have a a slightly different url which is just backslash posts and we can see that there are tons of posts that we can download here so i'm gonna go back into our code and i'm going to replace this url with our new url which is almost the same let's do let's add the s for https and as you saw in this website it's this no longer is giving us a single post it's actually giving us an array you can see the bracket here the open bracket of posts so we have an array of posts so when we go to decode it we need to decode it into an array of post model and then this new post should actually be called new posts because there's going to be a bunch in that array and instead of just appending it here we will set self dot posts equal to new posts all right we're gonna run the simulator one more time and hopefully if everything goes well we now have a bunch of posts coming through on our app beautiful so look at that it was that easy to change out our url to get in a whole bunch of posts and we are successfully downloading data from the internet and you noticed that when i ran that it loaded those posts extremely fast and that's it for coding in this video i just want to quickly just go over some of the really cool things that we did to make this super efficient in our code and firstly when we come down to this download data here we created this super handy function that is downloading data from any url and we're using a url session.datatask and the cool thing about this data task is that it automatically goes on to a background thread so we're going on to the background thread and when we're downloading data and after we get that response here we are checking that we have good data and we're calling our completion handler and now you guys are really becoming expert developers because you understand how this completion handler works with this escaping closure and we're using the escape enclosure again because this is asynchronous and because it might take some time between calling this data task and returning some data so we use this at escaping and it's going to return us some data and after we get that data in our results here we are then going to decode the data very efficiently by using the codable protocol and we're going to turn the data into an array of post model and of course when we went to actually append those posts to the post model we did it on the main thread and to avoid cases where we create strong references we used weak self and just to point out again that we need to do this from the main thread if i comment this out and i remove this question mark here and i go to run this xcode's actually going to throw us a quick error here and we get this purple error that publishing changes from the background thread is not allowed so this is telling us that we need to be on a main thread to actually do this so super helpful of xcode to actually give us that warning in case you ever forget to do this and let's put this back into our code so hope you guys enjoyed this video if you are confused about the codable protocol about weak self about background threads or about the escaping closure i covered all of those in previous videos in this course and i highly recommend going to check out those videos and now that we learned how to download with the escape enclosure we're going to jump into a new swift framework called combine where we can actually do the same thing here we can download data but we can use arguably a more efficient method than these escaping closures i'm going to show you guys that in the next video so thank you for watching as always i'm nick this is swiffle thinking and i'll see you in the next video bye
Info
Channel: Swiftful Thinking
Views: 2,036
Rating: undefined out of 5
Keywords: SwiftUI download, SwiftUI download JSON, SwiftUI API, SwiftUI with API, SwiftUI download from internet, SwiftUI download JSON from API, SwiftUI download @escaping, SwiftUI @escaping with JSON, Swift download JSON, Download JSON Swift, Download JSON from API Swift, Swift download from API, How to download from API Swift, How to download JSON Swift, How to convert JSON swift, Swift convert JSON from API, Swift REST API, SwiftUI REST API, SwiftUI URLSession, URLSession SwiftUI
Id: h42OHc5CRBQ
Channel Id: undefined
Length: 30min 55sec (1855 seconds)
Published: Thu Apr 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.