Download coins using a View Model and Data Service class | SwiftUI Crypto App #6

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] welcome back everyone i'm nick this is swiffle thinking where we cover all things swift and swift ui related in the last couple of videos we were setting up our screens we created a model we created a view that can hold a bunch of those models with all the data but we do not yet have our coin data so in this video we are going to create a class that is going to manage downloading all that data from the internet and like i mentioned in the introduction we're using mvvm architecture we're actually expanding on traditional mpvm by adding an extra layer between the view model and the database and we're going to call that basically a service so our view model is going to reference this data service and this data service is going to contain all of the logic that is dealing with the database so it's downloading all the data decoding all the data and then returning that data back to the view model so in this video we're going to set up our first of a couple data services in this app and again if you did not follow the swift ui continued learning playlist i highly recommend watching that playlist before this one because we're going to be downloading with combine and we're going to use a whole lot of the features such as background threads and subscribers a bunch of things that we covered in that playlist and i did that playlist first on purpose because i do not want you guys to get confused as we jump into this but by the end of this video we're gonna actually download all the data and we should be able to see it on the screen which is super exciting okay welcome back everyone i am back in our xcode project of course and in the last video we set up our list which would look cool if we had some data to put in this list other than this one sample bitcoin and in this exciting video finally we are going to actually download some coins from the internet put them into this list so hopefully by the end of this video the screen looks a little more like this screen where we have all of these coins that we can see and scroll through all right so we're going to download data and of course because we're using mvvm all that logic is not going to be done in the view instead we're going to start at the view model so here we have our view model and we could actually put that logic directly into the view model here we could add a function down here let's say funk download data and we can add all of our logic for downloading the data and then we could just append it right to this all coins and everything would work but when you are developing these more complex apps it's usually more efficient to create an a separate layer that manages all of the downloading of the data so this way the logic for downloading the data is actually separate from the view model so this view model is going to be specific for the home view but the downloading the data is actually more generic than this view model right so this view model is just for one specific view but downloading the data that could be used on a bunch of different screens a bunch of different views a bunch of different view models so instead of adding the logic into the view model we're going to actually create another class and then reference that class within this view model so what i'm going to do is outside of these folders i'm going to right click and create another new group and i'm going to call this services i'm going to move it below the extensions and the services folder is basically going to be all of the third-party services that we are going to use in our app so the first service we're going to add is to download the data from coin gecko it's going to be our coin data service but if i were to add other services in my app like maybe an external database or an analytics service i would put all the code for all of those services into this folder so here i'm going to right click create a new file and this will be a swift file and i'm going to call it coin data service go ahead and click create all right and let's create a class we'll call it coin data service open the brackets and in here we're going to have an array of coins so it's going to be an at published var we'll call this uh all coins it'll be of type array of coin model we'll set it equal to a blank array to start and the reason we're using the at published in here is because this because that then makes this a publisher and if you followed my swift ui continued learning playlist we learned that publishers can then have subscribers so from our view model in a second we're going to subscribe to this publisher so anytime this publisher gets updated with data all of these subscribers are then going to receive that same data so that's how we're going to get the data from this published array to our view model array i'll cover that a little more in detail when we actually get into it but for this class when we init the class we're going to call a function so let's create a private func we'll say get coins open close parentheses open the brackets let's call it from in our init we'll say get coins and i made this private because we're only going to access it from within this class we're never going to call get coins from outside of this class and now the first thing we need is a url where we want to download data from so in our models in our coin model file that we set up earlier we had copy and pasted this url here so i'm just going to copy that and i'm going to go back into the coin data service and in this function we're going to say guard let url equals url open the parentheses string and this string of course is going to be that url and then after this we'll say else return and just to run through again where this url is coming from if i go into coin gecko if i go to the coin gecko website they have their api here and we went to the markets api and we added the currency as usd we wanted the order to be by market cap descending 250 results per page we're only going to get the first page right now and then sparkline be set to true and we wanted the 24 price change we then clicked execute and when we ran that it gave us back the url that we needed to request from this is the url that we have and then we could see a sample of what the actual response was going to be and based on this response we set up our coin models so this is basically an array of coin models that we're getting back so this data that we see right here on the screen should be the exact same data that we get when we call our api and we're about to find out if we did everything right because if we did everything right we're going to get all this awesome data so going back into the code we are we now have our url and then we are going to download it using combine because combine is so powerful and it's definitely the future of ios development so i highly recommend anyone learning swift swift ui to get comfortable with combine we're gonna use it and to do that we're gonna we're gonna call url session and we're just gonna use a regular url session dot shared dot data task and we're going to look for the one with a publisher and for url click enter of course we're going to pass in our url the first we want to do when we subscribe to this publisher is that subscribe on the background thread so we'll call dispatchq dot global and the quality of service i'll use dot default now i believe this is actually going to be default on the background thread anyway i believe that's what the data test publisher does by default but it can't hurt to just make sure we are on the background thread here while we're on the background thread we then want to try to map the results that we get back from the publisher so i'm going to call try map and on this we're going to click enter and this is going to be the output that we get back and we want this to return some data data not date and in here we want to check that we do have good data from the output so first let's set we'll say guard let response equals output dot response as http url response and then we want to make sure that http url response has a valid status code so we'll say response dot status code is greater than or equal to 200 and response dot status code is less than 300 then we'll say else so if it is not an http url response or is outside of the 200 range we are then going to throw an error and here we'll just call url error and i think we can do bad server response i moved a little quickly through this because i've covered this a bunch of times in the swift ui continued learning playlist you can google url response status codes and these are like generic across the internet basically the 200 range means it signals that it is a successful response so if we can get past this guard here we can then return the output dot data after we're sure we got this data let's then return to the main thread so we'll call dot receive on we'll say dispatch queue dot main we'll then decode it so we'll call dot decode and we need to type to decode so we know that the data coming back from this is going to be an array of coin models that's why we made the coin models so in this type we're going to call array coin model dot self and the decoder is going to be a json decoder open close parentheses and that's because we know this is json data so if this decoder is successful it's going to give us an array of coin models and then finally we can sync that array and for the completion let's click enter we'll call this completion we will switch on the completion open the brackets and we'll do case dot finit dot finished if it is finished that means it's successful we'll just break we don't need to do anything with that if it is case dot failure we'll say let error colon and then we'll just print out here the error so we'll print error dot localize description this is just like a human readable format version of this error and finally if we do receive this value we have returned coins so we can call self dot all coins and we'll set it equal to returned coins and we know because we are good coders that this self is then going to create a strong reference to the class so if for some reason we needed to deallocate this class uh the system actually wouldn't because of the strong reference so instead we have to make it weak we do that with a weak self then basically we just need to add make this optional with a question mark here if you're confused what weak self is i covered it in detail in its own video in the swift ui continued learning playlist and i highly recommend going to check that out and then coming on back to this so if this is all successful we should then append the return coins to our all coins array which is up here finally we have this warning message here that the result of this is unused and that's because this is a subscriber and because subscribers can be canceled at any time we need to store them somewhere so if you've been following my courses usually i create a var cancelables of type set of any cancelable and we need to and we don't have access to it because we have not yet import combine set of any cancelable and then we open close parenthesis and then on our publisher we just store into the cancelables and that works and that's great sorry this should be an equal sign and this would work if we ran it but the problem with this approach is that it is then tough to figure out if you wanted to cancel it later it's tough to figure out which item in this set is referring to this specific data test publisher because if we appended a bunch of different publishers to this cancelable set we would then need to figure out which one we want to cancel if we ever try to cancel one so instead of creating a set this time i'm going to create a single can any cancelable variable so i'm going to call this var coin subscription and it will be of type any cancelable and i'll make it optional so instead of this store incansables we're just going to set coin subscription equal to this publisher so this way we have our subscription right here and when we want to cancel it we can just access this directly and of course i'm setting this up because we do want to cancel it so when we call this that has publisher it basically just assumes that this url could potentially be sending us data over time so when we go to call this it's assuming that it might publish values now and then it stays listening in case we have more published values in the future but we know that this url is just a simple get request so it's going to go to the internet come back once it's not going to come back like 5 or 10 times over the course of a minute or something like that so because it's just one single get request if it does come back this one time down here let's just cancel it after that so we'll say self dot coin subscription and we'll just cancel it it's not a big deal if we don't cancel it it's not going to really take up that much memory or really affect our app in any way but we are being good coders and we might as well cancel it because it's not going to really do anything after it already returns once anyway all right so when we initialize a coin data service it is going to initialize and call getcoins the getcoins function is going to get this url it's going to get the data from the url hopefully check for a valid good response if we get good data it's going to try to decode it into coin models and then if we have an error it'll print out the error but otherwise it will append the return coins to where all coins are right here so now all we need to do is get this all coins published array into our view model so i'm going to click the plus on the right side here and when we're on the right editor i'm going to open up the home view model all right so remember this home view model is the view model for our home screen the first thing we need to do in here is initialize this coin data service so we'll say private let we'll say we'll call it data service and we'll set it equal to a new instance of coin data service so when we initialize this coin data service which we are doing right here it is going to call this init it's going to get the coins automatically and once it gets the coins it's going to append them to all coins and now we just need to get the data from this all coins to this all coins so from the data service back into our view model and and i labeled them the same way they're both called all coins this one in our view model here is going to subscribe to this publisher in our data service so this way anytime we append to this array here because it's a publisher anything that is subscribed to this publisher would then get updated so in our view model here we're going to create a funk add subscribers open close parenthesis open the brackets and let's get rid of our init here and just call add subscribers in our knit so in this add subscribers let's subscribe to the data service dot all coins i'm going to use the one with the money sign here because that is a publisher so this data service that all coins is the data service dot all coins here okay so when this gets published this subscriber is going to also get notified and get the same values so when we in our get coins we're going to append at the bottom here we're going to append all coins to this and once we append it at the exact same time that we append to this publisher it's going to publish that value to this subscriber on the right side here so all we need to do here is then call dot sync and we're not going to worry about the errors right now so let's just take the receive value here and all we need to do is take the published value which will click enter this will be returned coins and here we'll just call self.allcoins equals returned coins and again we know this creates a strong reference so just to be safe we'll add a weak self here and make this optional and then we're getting that result warning because we haven't stored this subscriber anywhere so in this home view model we're not going to cancel these subscribers ever so we're just going to add them into a set we'll say i'll say private var uh cancelables and we'll set that equal to a set of any cancelable and again we need to import combine any cancelable and then we'll just store this in the cancelables all right so one more time i i know i'm repeating myself but i know some of you are going to get confused from this because i get so many of these questions but how this is all working because this is like the magic of our app and it's really important to understand this our view our view as a reference to this view model and this view model is then has a data service which we are initializing a new coin data service right here and when we initialize this coin data service which is this class here in the initializer it is calling get coins this get coins function is gonna go to our url it's gonna download the data it's gonna check that it's valid data it's going to decode that data and then it's going to take that data and append it to the altcoins array which we have up here when things get appended to this array because it is published anything subscribed to this publisher will also get notified and back in our home view model we added these subscribers and the first subscriber here is subscribing to the data service dot all coins array this array is this published variable on the right so when we get data published here it's going to also publish here because we're subscribing to that data so anytime we change the all coins we're going to also get that returned here and all we're going to do is take it here and then just append it to our all coins array all right that was a lot of talking and explanation but i hope you guys are following along and let's uh x out of this let's jump into our home view now we have our home view model and let's resume it if we did everything correctly when we resume this preview it should actually download some coins and it was like magic guys that was so awesome i hope you guys now have these coins coming through and they look like they're all formatted correct for me and you should be able to scroll on this list alright guys so i hope you are at the same point now um your screen should be loading all this data which is so so cool if for some reason it's not loading this data i would say check if anything is printing out to your console make sure you set up these subscribers correctly and then if all else fails maybe check on your coin model because if for some reason you set up the coin model wrong the decoder might fail but most of this is optional so it should be a very slim chance of the decoder actually failing and i hope that at this point in this video you guys now have this data pulling into your app and it looks so awesome all right guys so our screen is finally coming together we do still have a lot more to do to make this a professional app of course so that's it for this video i think this was one of the most exciting ones for me because we finally get to see all this data coming onto the screen we've been setting this up for a couple videos now so as always i'm nick this is swiffle thinking and i'll see in the next video you
Info
Channel: Swiftful Thinking
Views: 2,613
Rating: undefined out of 5
Keywords: SwiftUI download, SwiftUI Downloading, SwiftUI download with combine, SwiftUI codable, SwiftUI json data, SwiftUI coingecko, CoinGecko API, SwiftUI download data with Combine, download with Combine, Combine download Data, SwiftUI publishers, SwiftUI URLSession, URLSession SwiftUI, publishers swiftUI
Id: TlJUMVKtUhc
Channel Id: undefined
Length: 23min 10sec (1390 seconds)
Published: Sun May 30 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.