Swift: Build Covid Tracker App (2021, Xcode 12, Swift 5) - iOS Development UIKit

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on guys welcome back to another swift video in today's video we're going to be building out a pretty simple covid tracker i've been wanting to build out a whole app on this channel again shorter videos have been kind of the the most recent thing so here's the app we're going to be building out we're going to bring in this pretty sweet looking uh graph up here we'll talk about formatting data the dates the numbers we'll also add in a ability to filter out the cases by state luckily cases are going down here in the u.s we'll talk about of course getting the data from an api and basically everything in between so um fairly bare bones but we'll set everything up in a pretty decent architecture so you'll get a good glimpse of you know how to build out an app so if that all sounds good make sure you start by destroying the like button down below for the youtube algorithm helps push the video out and hit the like button if you're just into ios and if you're into ios and want to stick around hit subscribe while you're at it to be notified for new updates and to keep the channel going and growing together that all said let's get into the video let's go ahead and get started by opening up xcode and creating a brand new project here we're going to go ahead and stick with the app template under ios and let's go ahead and give this project a name of covid tracker you want to make sure your language is set to swift your lifecycle ui kit and your interface's storyboard will be doing your ui programmatically but no swift ui today go ahead and create the project and save it wherever you'd like i'll toss it onto my desktop here and first things first we're going to go ahead and collapse this right panel i'll jump into my view controller file here i'll bump up that font size and maybe we'll go ahead and also select a simulator and just give it a run here so we can actually build and start seeing something hopefully show up in our simulator here and while it's doing that let me expand our xcode window here and we'll dive into basically what we want to do now before we start writing you know the steps that we want to take to build out the app i want to bring your attention to the api over here that i've got opened up in a browser if you head on over to this website kovidtracking.com data api version 2 it's a pretty great historical data api for covid cases specifically in the uh us so they give you national values single day values and then you can also filter down by state you know i apologize if you aren't from the us but you know this is the easiest api that i found you don't need to sign up you don't need an api key it's just kind of free to use so basically like you guys saw what i want this app to do is when you boot it up it'd be nice to see you know values of like the federal level so the entire states and then maybe a filter option to filter out those values by state and maybe if we have time we'll go into filtering out on a daily basis so that said what do we first want to do so this first controller here this is going to be basically our data of covered cases and we're basically going to show uh cases based on the scope that we're looking at so we launch the app it should be at a national level and that we can filter down on a state-by-state level so that all said let's go ahead and start building this out so first things first let's add a title here and we're going to go ahead and say this is going to be maybe by default us national uh covid cases or maybe this might be a little long so let's just go ahead and actually call it uh covet cases and maybe we'll have a subtitle which is going to show you know the scope of what we're looking at which in this case would be national so before we go ahead and hard code that title let's talk about in a nutshell the pieces that we're going to want so i'm just going to comment it here so first and foremost we're gonna want a way to call apis or the api endpoints i should say and we're gonna want a way to have view models to configure our view we're gonna need to have a view and i'm thinking we're gonna stick with the table view and based on how we do on time we'll we'll bring in like a nice chart to plot the data and let's see after we've gone ahead and brought that stuff in we're going to also want to have a way to filter and then slash fetch uh or rather pick let the user pick uh the state that they want and then we'll want to update our main ui so it sounds like we're going to want two main controllers the first one here is going to be uh our uh covet controller or our covid you know call it whatever the heck you want and then i'm going to create another view controller here and this is going to be maybe a state selection controller so we're going to create a ui view controller here subclass a ui view controller and this is going to be a maybe let's call it a filter view controller to make it a little more extensible if we so choose to so let's go ahead and create this save it and in here we're basically going to allow the user to pick a state so we're going to go and give it a title of select a state so that's looking pretty good let me just drag this up and yeah so we want the view controller to start off here embedded inside a navigation controller so we have you know the navigation bar and all those semantics so we can do that programmatically but we're gonna cut a corner here for the sake of time and i'm going to go in the storyboard and just select this controller here in the toolbar we'll go ahead and hit editor and we're going to hit embed in a navigation controller which does this for us and then we'll select the navigation bar on that left hand controller there open up the attribute inspector and we're going to go ahead and check that second box here for prefers a large title go ahead and run your app and now you'll have your you know title showing up here as you would expect next up we want to create the object that's going to handle our api calls so we're going to be super creative and call it a api caller i'm going to go ahead and say api caller.swift and basically it's just going to be a singleton class that we leverage so we'll say there's a shared instance of this api caller we're going to privatize the initializer here and if you think about you know what do we actually want to get back from the api caller in other words what functions do we want on it we're going to want basically to get covered data and of course this is going to have some sort of scope and completion handler we're going to also want to get a list of states so we're going to say get state list with also a completion handler and i'm just going to be a little lazy and stick the models down here in the api caller so we can use them directly so we're going to say models and we're going to want a state model and a state model we want to keep it pretty simple it's going to be something codable we'll go ahead and do that we'll get that from the api and then we're going to want a bunch of models for our actual data as well so let's go ahead and also think about how do we filter down this covet data right we want to get it for either nationally or a particular state so i'm going to go ahead and put a scope on here maybe we can call it data scope which is going to be an enum and the two types that i just mentioned is we can get national data or we can get state data for a particular state object and now we'll go ahead and do here is we're going to say get covered data for a scope and this is going to be a data scope and of course there's going to be a completion handler on here which will be in escaping block which is going to give us a result back let me close this right panel to give ourselves a little more room and we'll go ahead and line break all this goodness and our result is going to give back you know some type of model i'm just going to call it a string for now so we can actually just write it out so something is you know here and working and this block is going to return void now similarly our uh get state list function here is not going to take in a scope but it is going to similarly take in a completion handler and the completion handler once again will be escaping it's gonna return a result in the success case we're gonna have a array of states if something goes wrong we're gonna have an error hopefully and this whole thing returns void not voting so let's go ahead and fix that all right so now the next thing we want to do which is everyone's favorite part let's go ahead and take a look at our api responses and figure out you know what the urls are and what the response json looks like so let's start by looking at the list of states since i think it's the simplest api call here here is the url so i'm just going to right click and copy it and maybe i'll go ahead and create a constant uh struct inside of here we'll go ahead and just drop in the urls in there so we can just reference them more easily so we'll say constants and this is going to be static let all states url will be a url with this string and we'll just go ahead and paste that in notice you don't need an api key which is kind of nice and let's see what the response of this guy looks like so let's go ahead and simply click on it and we get a whole lot of json so we can exclude in our codeable model the stuff we don't really care about so i don't care about the links i don't care about the meta key here i do care about data which looks to be a array of these uh state objects is what i'll go ahead and call them so there's a bunch of things in here like census and this and that however i don't really care about the majority of this all i really care about is the name of the state and probably the state code which is what we'll use to go ahead and get data for the state code so let's go ahead and just uh bring that in here so we have a root key of data name and state code so we'll go ahead inside a state we're going to say there's a name and there's a state code which is also a string and similarly we're going to go ahead and say there's a struct of a state list response which is codable which will have data which is a array of state objects just like that and that's actually sufficient to write out this api call so let's go ahead and uh write this out and actually hook it up to our ui you might be wondering why i'm starting with this particular api call it's kind of simple and straightforward so i figured it's probably easy to start with it so let's go ahead and write this out so first and foremost you want to grab the url so we're going to say garlic url is our constants and grabbing our url we do need to unwrap it since the initializer is failable next up we're going to create a url session task shared we're going to do data tasks with a url and a completion handler passing in that url the completion block gives us a data back a response and a optional error we're gonna validate that we do in fact have some data and we're gonna validate that we don't in fact have an error otherwise something has gone wrong we probably should return error there in the completion but i'll be lazy and skip it for a minute and uh next up we want to convert the response data here to our model so we'll go ahead and say our result is json decoder rather try to use json decoder to decode this state list response dot self from said data and once we've gone ahead and done that we can get the states out by saying results dot data i guess here and finally we can pass it into the success case in our completion handler just like that and in the catch here we want to catch any errors that occur so we can pass back the that to the caller as well and we should probably make an attempt to spell things correctly since it's kind of important so there's that and then finally we'll go ahead and kick off this task to go ahead and fetch so now that we've got this api written let's make sure it actually works so we created that state uh you know filter controller so i'm going to go ahead and create a bar button at the top right of our uh app here when we first start it up and that's going to allow us to filter so let's go ahead and create a function here create filter button and we're going to create that function right down here create filter button and basically we want to hang on to the scope that this controller is rendering for so by default the scope is going to be the national scope so we're going to say api caller data scope and this is going to be national by default and here what we can go ahead and do is we want to create a bar button item so we're going to say navigation item dot right bar button item and what we're going to do is we're going to show a title which correlates to whatever scope we're kind of looking at at that point in time but before i do that let's go ahead and fill these out so style done target self and this is going to be did tap filter all right and let's go ahead and create this function as well which is going to be a objective c selector just like that and basically for the title here what i'm going to go ahead and do is we're going to resolve a title up above so we'll go ahead and say let title or maybe i should say i don't know button title so you know conflict with the view controller's title property is going to be a string and essentially i'm going to go ahead and switch on the current scope and we are going to say if it's national we're going to go ahead and say go ahead and return national and otherwise if it is a state we have the state uh model here we can return uh state dot name which is a part of our model here and that's basically how that button is gonna look and when we tap on the button what do we want to do we want to create the filter view controller we also want to go ahead and wrap it inside of a navigation controller so we have you know a navigation bar so we'll go ahead and make it the root right there and then finally we want to go ahead and present this controller with the animation and no completion parameter here so go ahead and give it a run and let's see if we can see that other controller we can in fact see it's looking a little weird because we didn't set a background color to it so let's go ahead and work on that filter view controller which i put right here so let's go ahead and first set a background color so it doesn't look so strange we'll say system background now what else do we want here we want a completion handler so we're going to say public var completion and this is basically going to pass back to the caller you know which state was selected so it's going to be optional so let's go ahead and do that and we'll call it once the user taps on one of the states in the table view that we're about to create so we'll create this table view here and this is basically going to be responsible for showing our list of uh states so we'll go ahead and create a table view and we're going to say frame is zero style is grouped go ahead and return that table at the bottom of that closure and of course don't forget to register a cell here we're not going to use a custom cell we're going to keep it simple for the sake of time here but once we've gone ahead and created that go ahead and add your table as a sub view you want to assign its data source as well as assign its delegate and respectively you want to conform to those interfaces those protocols so we'll conform to them up here so let's go ahead and spell that correctly otherwise it's not going to be able to find it and let's go ahead and further implement so we need to override view data layout sub views go ahead and call the super function for it and we'll give our table view here a frame to match the entire bounds of this controller and then we want to have a bunch of table view functions here so we'll go ahead and say uh number of rows we're going to return something we'll just do 0 for a quick second cell for row at index path we'll need to dequeue a cell in here and i realize i'm going a little quickly i'll talk through kind of what i did um once we kind of get to a decent stopping point in this controller but basically we'll go ahead and dequeue a cell here we're going to return it like that we're going to assign its text label to something in our case it'll actually be the state's name and then once the user selects a particular row we want to deselect it we want to get the state and then we want to call the completion handler so we'll say call completion and basically dismiss as well so now that we've got all this set up we first need to fetch a list of states here and the way we're going to do that is at the bottom of view did load we'll go ahead and say fetch states and this function is going to basically do what the name implies it's going to do it's going to fetch our states from our api caller so we'll say shared and we're going to say go ahead and get a list of states and this is going to give us a results back now what we want to do is we want to switch on said results and in successes case we're going to get a collection of states and in the failure case we get an error which for now we're just going to print it of course in your actual app please please please manage the error correctly we're going to assign the states to a global states property which we're going to create momentarily as soon as i capture weak self here so we don't cause a memory leak and let's see let's go ahead and create that we'll say uh private var uh states is going to be an array of states and essentially once the actual state has been set we're going to say table view go ahead and reload yourself so this looks good to me now in our number of rows we are going to say states.count for the number of rows for the cell for row we're going to get the nth state in our array so we'll say states and we want to get index path dot row and here we're going to say state dot name and let's see what else do we need to do so now here we want to get once we select a state we want to get to the nth state that was selected similar to what we did in cell for row and we want to call the completion handler passing in the state and finally we want to call dismiss with a animation and nil for completion here the other thing you might want to do is add a cancel button in case the user you know doesn't want to change their scope so we can actually do that at the top here maybe we'll add like a little x button we'll say navigation item dot left bar button item and this is going to be a ui bar button item with a style of clothes and maybe a target of self in action and this should be a selector did tap on close and let's go ahead and just create this selector i'm just putting it wherever basically but try to organize your code but in here we'll go ahead and say true and nil so let's go ahead and run this i know we just typed out a lot of code and let's make sure that we can actually see a list of states so i go ahead and tap on this and it looks like i don't see our list of states so what the heck is going on uh it looks like we're actually calling something from the main thread or from the background thread that should be on the main thread and i suspect it is our table view reload which actually xcode is telling us is what we screwed up of course keep in mind anything that is ui related do it on the main thread um and anything you know networking should most likely be on the background thread so once we go ahead and do that we can see that we do in fact get a list of states we can actually go ahead and close this out as well and uh right now we tap on it we dismiss it but we're not actually passing back the state to the caller because we never actually assigned the completion handler in the presenter side so if we go back to the presenter we can say vc.completion is basically going to give us a state back we're going to want to capture weak self and what i'll go ahead and do here is we want to say self.scope is going to be a state with the selected state pretty simple and i'll also go ahead and we we want to say fetch data now so we're going to say dispatch queue we could actually just do this in the background now that i think about it now we don't have a fetch data call to actually you know go ahead and fetch our data but we will go ahead and say private func fetch data and this is going to fetch our data for our current scope so what do we need to do we want to call self dot fetch data and we're also going to go ahead and say create that filtered button because since the scope is different now the title for it will go ahead and change so now that we've got this here we want to actually write out the api call before we call it from there to fetch our covet data so now in here we want to most likely do the exact same thing so i'll actually go ahead and copy and paste this but our url is going to differ so let's go back to our browser and let's go ahead and take a look at what the data url is going to look like so if we have uh the state picked we want to get a single states so this is a single state's metadata but we want to get historical data for a state is what i'm looking for and basically this is the url here so we can go ahead and actually copy this and i'm going to stick it into our constants here so we'll go ahead and say covid state data url and actually i'm just going to make this a string because we'll need to tack on the state that we care about so you can see here that uh this passes in the states code so we'll go ahead and pass in you know whatever states code and actually it doesn't really even make sense to make this a constant so what i'll actually go ahead and do is when we call this uh fetch here we're gonna need to create the url so i'm gonna say url string is going to be a string and we're gonna switch on the scope and if the scope is national we want to do something we're going to return you know some url string and if the scope is the state we have a state model and we'll go ahead and return this but inside of the actual string we're going to go ahead and stick in we're going to interpolate the state dot the state code and we're going to go ahead and lower case that and let's see why this is yelling at me because i forgot to actually assign this so instead of returning it we're going to say this is a url string and similar this is the url string all right so that is the url for the state by state let's take a look at the url for the national level so that would be up here and we don't need to compute anything in here because there's basically just one url so what you could do is go ahead and just stick that in right there and this is all under the assumption that the json response is somewhat similar so now that we've gone ahead and done this you can actually construct a url from this url string so this is going to be url string and we're going to call the api respectively like that now what we want to actually do is uh figure out what the codable model looks like so i'm going to go ahead and click on this national data response and it is beyond enormous so this is kind of hard to actually even read so let me actually try clicking the state response hopefully that's a little less crazy uh and of course this one's not that easy to read either it looks like it's trying to it's trying there but it's not working out too well so let's see it looks like we have a meta and i would hope we have a data in here as well now when this stuff is kind of hard to read like this the best bet that you have is to try to serialize uh deserialize that json directly here and read it in your console so let me try to do that actually i'm going to go ahead and say try to use json serialization and create a json object with the data and we are going to allow fragments and then i'm just going to go ahead and print out the results in hopes to actually figure out what that structure looks like because it's a little crazy in the browser so let's go to the view controller and we're going to say api caller shared and we're going to say go ahead and get covered data for the current scope and here is our completion now in our actual uh block here what we want to go ahead and do is switch on the results in the success we should have some sort of data back and in the failure we're going to have a error back that we're going to go ahead and be lazy and simply print out for now and of course we want to call fetch data as soon as the app also opens because it's going to be set to national by default so let's go ahead and look at that response getting dumped out right there looks like it's an enormous response not surprised so i'm going to go all the way up here and take a look at what this looks like so we do get a data key here which looks to be pointing to an array and it has each of these uh blocks inside of it so let's see let's see what each of these has so i'm going to go ahead and come back to the api caller and go down to the models now we're going to start creating some models here so we're going to go ahead and say we have a covered data response which is going to be codable it has a data and this is going to be let's see how this data is structured so every data looks to have a cases key in it which points to some cases data it has a date in it it has an outcome in it which is kind of depressing i think it shows you who died um it shows you states it shows you some testing data so let's actually figure out what we want to show in our ui so um i think cases is probably the most you know the most uh common thing you would want to show so there's total there's value i guess what we want is value for the cases so i'm going to go ahead and i'm going to call this covid uh day data since it represents a single day we'll go ahead and create this here as codable and each of these days has a cases key which points to another dictionary and in here what i care about is the key for total which points to value so let's see if i do this correctly so this is going to be coveted cases which will be another model down here code with cases codable and in here we have value and let's see so cases so we have total let's make sure i do this right so this actually has total in it so cases is pointing here which has total and then total is another dictionary that has a value key in it which is an integer so i'm going to go ahead and call this total cases like so which is once again codable and finally it has a value which is a integer so hopefully all my errors go away and we can now decode to this so let's try doing that so instead of whoops wrong one instead of doing this whole dumping nonsense we're going to use the decoder to try to decode our appropriate response from the data now from this what i want to go ahead and do is actually now that i think about it let me open that up again what the other thing that we want in here actually is the date so we have date represented as a string because it'd be silly to not show the date and that's at the same level of at cases so if i come down here i'm gonna also go ahead and let's see if i can find it i'm gonna go ahead and say date which is going to be a string and we probably want to pass back a better model right so these are our codable models but what i probably want to go ahead and pass back is a struct that is something like this so we're going to say covid day data and let's make sure i didn't already use this looks like i did let's go ahead and call to something else we'll call it uh day data and we want basically a date in it and we want a count in it i guess because we don't want the caller to have to go ahead and like traverse all this codable data because that would kind of be a pain in the butt to do so let's go ahead and see if this works so we've got this hooked up already now result is going to have data which has uh quite a few things on it's actually an array so what i'm going to go ahead and do is we will print out the count of this and i'm also going to change the signature of the function up here and in the success case we're going to return an array of day data so let's go ahead and give this a run and let's make sure we are in fact getting something printed out that is valid so it looks like we're getting a coding error here so let's see no value associated with coding key for name and that's an int value let's see why that is what did i screw up so we have data we have covered day data we have total and then we have value i don't see name in here let's make sure we're using the proper object so we're saying it looks like we're saying state list response here which is not what we want we want the covid data response covet data response model since that's the new one we created and it still looks like we're getting an error here saying json key index 419 and let's see string value cases into value is nil so it looks like in some value in some cases this cases is optional or it's not what we expect it to be so we can go ahead and make that optional let's see if that resolves it all right looks like we still have an error so let's see what's going on index 419 coding key cases for an int value expected into value but found null instead so let's see for our value i think is what it's actually complaining about so let's try making that optional so this whole thing is a little bit of a guess and check you know when you're working on a larger app you'll see you know something appropriate but now we get our count back which implies that the decoding was successful so cool so now that we've got this going on the next thing we want to do is convert our actual response into the models we want to return to the caller so one thing that we do want to go ahead and do is convert our date objects so our date objects are actually returned as strings if we look at you know any of let's see if i can find an example here if we look at the date objects in our actual um response we we know we want to convert that to a to actual date object so what i'll go ahead and actually do is we're going to say for each of these we're going to have a model in and each of these models basically has a date so let's go ahead and just print these out what i want to do is figure out what the format of that string date is so i can create a date formatter that looks like it so it looks like uh we have the year the month and then the day right there so what i'm going to go ahead and do is up here we're going to create an extension and this extension is going to be on date formatter we're going to create a formatter so we'll say our data formatter or maybe we'll go ahead and call it day formatter it's going to be a particular type of formatter and this is basically going to allow us to convert the string that we get back into a data object so we'll say date formatter is what we want to create we're going to want to return it here and let's actually go ahead and just call this formatter so it doesn't give us the redundant naming now in here the most important part we're going to say the date format is basically going to be this and this is going to be year this is going to be month and this is going to be day you can also alternatively not alternatively but in addition i guess you can also assign the time zone as well as the date locale which i'll just use current and essentially now what you can go ahead and do in this api call is you can actually compact map this stuff so we'll go ahead and compact a map and i'm gonna go ahead and say this is models and this is going to be a day data and we are going to convert so we'll say date formatter dot formatter dots formatter this one right here day formatter and we want to create a date uh from a particular string and that string is going to be dollar zero dot date and we'll also go ahead and get a count here which will be dollar zero dot cases and the one thing that is uh tricky here is that this returns an optional so i'll go ahead and say guard let dates is going to be this otherwise return nil and this is going to be date here it will toss a return right there so what we're essentially doing is we're taking our codable models and we're compact mapping them to the models that we want to pass back in our completion handler and these are going to be uh day data models like that and if you make the explicit type there your error will go away because the compiler sometimes is just not smart enough to pick up on what you're trying to do and then finally my long spiel comes to an end we go ahead and pass back the models to the caller and the way that we'll make sure that this is in fact working well let's make sure this is correct first so cases uh we want from that the cases dot total dot of value and actually this is also optional so what we'll also go ahead and do is we'll say let's let value is this and we're going to pass in the value here just like that and let's make sure those errors go away and now in our view controller we should be getting day data so we'll go ahead and simply print out daydata.count to make sure we're getting it back we're almost done stick with me alright so we're definitely getting the print statement still which means we're looking good so let's go ahead and assign this to a global instance of day data which will be here we'll go ahead and say private var day data is going to be day data and it'll be uh empty by default and once again similarly whenever we set to this uh on the main thread we're gonna update the ui now i mentioned uh adding in a chart but we're also first gonna bring in a table view we'll see how we do on time to bring in that chart we're going to say private let table view and this table view is going to be nothing more than a standard ui table view and we'll go ahead and say this is a table view like that we'll go ahead and bring in a frame of zero i'm gonna go ahead and return the table gonna register a pretty vanilla looking cell to its just like that and let's see what else do we want to do here we're going to go ahead and say reload data i'm going to go ahead and say configure table which we probably want to do before we make the api call and let's go ahead and bring in this configure function here which is going to do a few things first and foremost it's going to add the table as a sub view we actually don't care about the delegate we just want to show data so we're just going to assign the data source and we want to go ahead and conform so we'll go ahead and say table view data source and then down here i'm just going to go ahead and put it down here the table view stuff go ahead and say table and we're going to say number of rows is going to be our daydata.count our cellphone index we're going to go ahead and get our data which essentially is going to be from our day data the nth uh element and we'll also go ahead and dq a cell here so we'll say this is a ui table view cell and it's going to be table view dq a reusable cell with a identifier for the given index path go ahead and return the cell and the text is a little interesting so what i'm going to go ahead and do is we're going to go ahead and say create a text with data and i'm actually going to do this in a different function for the sake of just like cleanliness this function is basically going to create you know as the name implies the string that needs to go into the particular cell like so and the reason i did this here is because we're going to now need to convert the dates to an appropriate string as well so we can go ahead and come back to our api caller and i'm going to add another formatter up here which we can create this as like a pretty formatter and instead of you know using this format we can say formatter dot date style is going to be medium and that's just going to print out things to look a lot nicer and if we come back to our controller here we can go ahead and first get the string or the date string i should say and this is going to be our date formatter dot our pretty formatter and we're going to go ahead and create a string so let's see why this is yelling at me so this should be a let's go ahead and hit command b in case xcode is being dumb let's see what i screwed up here something is not correct there it is pretty formatter we want to get a string from a particular date which is going to be our data.date and finally we're going to go ahead and return a string which is our date string followed by a colon followed by data dot uh count now we're going to format the count here in a quick moment as well but just to get this whole thing working here let's go ahead and actually finish this up and run it so we want to capture weak self here just like that and i think we should be good to go so this should be self dot table view let's go ahead and give this a run this video has gotten way longer than i wanted it to but um let's see what the heck happened where is our table i think i forgot to assign a frame which yep i did so we need to go ahead and override view did layout sub views and we'll go ahead and give the table view a frame to match the entire bounds of our view so go ahead and give that a run and there is our data so march 7th 2021 that's when they actually stopped collecting data at this api this is the number of cases which is slightly frightening it's what 28 million which is a little nuts so the next thing i want to do here is i want to format this number to look a lot nicer because it's a little ugly right now there's no commas so what we could actually introduce here is a number formatter so i'm going to go ahead and create it up here and actually yeah we can leave it as internal instead of private we'll go ahead and call this a number formatter which uh the name kind of gives away its job so we're gonna go ahead and do that and we'll go ahead and say a formatter is a number formatter go ahead and say formatter and i think there is a format style or something like that on here i know you can also supply the locale let's see what i'm looking for number style and number style you can do you know things like currency which is not what we want decimal ordinal percent uh let's see if we actually can get away without assigning this because i think it'll add the commas for us and we're going to go ahead and say the total here is going to be self dot number formatter and we want to go ahead and get a string from a particular ns number and this is going to be created from our data which is going to be data.count just like that and now we're going to go ahead and drop in the count there and hopefully things are comma separated now this total gives us a optional it looks like it actually didn't bring in the commas so let's go ahead and first of all coalesce this to data.count and let's come up here and actually add a i think it's a separator or something like that grouping separator so let's see what this is grouping separator the string used by the receiver for a grouping separator interesting so there's currency always show decimal so we want the separator to be a comma let's see if i need to assign the number style here as well we i guess could use currency it's gonna add at that point a dollar sign which is not what i want so let's see what else is in here there's decimal none ordinal scientific spell out so scientific style format let's see what spell out is a style in which the numbers are spelt out in the language that's not what i want let's try scientific and see what that looks like apple's description is kind of not good looks like we have a error here because this gives us an integer so we go ahead and say this is a string instead and that should hopefully appease the compiler and we still don't have commas interesting so let's see i gotta remember how we actually use this formatter so we're gonna go into this formatter and i'm gonna see what is available to us bear with me so we can get a context we can get a string there is a default formatter behavior i think that is what we want so let's go ahead and see if we can use that so we can say default formatter behavior which returns a number formatter behavior so i think we might want to assign the behavior on here instead so let's see what formatter behaviors there are so there's there's defaults let's see what that gives us and if you know this takes too long then i'm not going to waste too much time on it it looks like it is taking too long so let's go ahead and give it one more try otherwise i'm gonna forget it because i just don't have i don't want to kill too much time on this so there's grouping separator uses grouping separator i guess this determines whether the receiver displays the group separator maybe this should be true and we're going to say formatter that's not how you spell formatter formatter and we're going to go ahead and say the separator is going to be a comma which it should pick up from the locale but you know i digress all right i'm going to probably figure this out after i end the video but whatever we'll forget that number four matter but this is basically uh where we're at let's go ahead and try to filter this so if i come here uh some of you might know i'm actually in new jersey so let's go ahead and look for new jersey here so we'll go ahead and hit this and it looks like we didn't actually actually we did we updated the data it was quite quick so it's hard to tell but you know 812 000 cases on march 7th boy that's a lot now the other thing i had opened here and i don't know if i want to get into this now since this video is kind of long is uh this chart framework to render out different kinds of charts because it'd be pretty cool if we showed a chart let's see if we can get away with integrating this fairly quickly so i'm going to copy the github url there we'll come to xcode go to file i'm going to go to swift packages and we're going to add package dependency we're going to go ahead and paste that in it's going to resolve charts just keep hitting next next next and essentially it's going to go ahead and bring in the dependency there is a couple things for example code in here but we could use you know like bar charts maybe or a line charts really subjective but uh bear with it while it brings in the framework should be fairly quickly and hopefully everything should still be compiling and what i plan on doing was adding a table header view so instead of just seeing this raw data having like a table header that plots out a graph because that'd be pretty cool so that all said let's see what we need to do so here we're reloading the data i'm going to go ahead and here also say self dot create table or we can say self.create graph and this create graph is going to basically you know create a graph for us so my computer is getting super loud with its fan which means that it's compiling which is good and i'm also going to come up here and import uh charts which it's still compiling it looks like so bear with it looks like we have a error in the compile so let's see no such module charts because let's see why so we're gonna see where charts is it's not actually popping up interesting so let's see what's going on so we definitely have charts brought in which i guess i can close up xcode and let's see if we reopen it if it resolves otherwise i'll bring it in via cocoapods this video has gotten way longer than what i wanted it to be but that's okay hopefully we get our nice chart coming in which will make everything look a whole lot nicer so let's go ahead and bring this in i'll go ahead and bring in charts not carts charts and let's see so it looks like it's not resolving so the other thing that i guess we can go ahead and do if we come back to this it does tell you how to bring it in via cocoa pods so let's see cocoapods installation it is just called charts so what i'll go ahead and do is close xcode we're going to go ahead and open up terminal we're going to cd into the project and do a pod init the reason it's not working with spm swift package manager is always you know a question um you could go ahead and debug it but generally it's kind of irrelevant how you bring in the dependency so long as you know you bring it in and it works is good enough for me so go ahead and bring that in lowercase.p and i'm going to go ahead and run pod install we'll see what happens with the duplicate dependency because we did already bring it in with spm but uh hopefully it won't conflict after you've gone ahead and ran it to install go ahead and open up your xc workspace that should have been created for you and let's go ahead and try to run this again in our 12 pro max the first time you give this a run after bringing in the dependency it is going to take longer to compile by virtue of you know just being a bigger project and having more source so bear with it here jump back to our view controller hopefully our error goes away and it's able to resolve charts otherwise this is going to be a part two so it looks like a successfully brought in chart and it is able to compile and launch and this is the part where we actually create a graph so let's see if i can remember how the heck to create a graph so so we have a create graph function here the first thing we want to do is actually create a header view and this should be an equal and at the end of this we're essentially going to say the table table views table header view is the header view we're going to want to say how to view clip it to bound so nothing overflows i will also want to give it a width and a height so i'm going to say view dot frame dot size dot width and same uh same thing for the height as well because we want it to be a square at the top of our table all right here comes the fun part for the chart so we're gonna go ahead and say our chart is going to be a bar chart view and we can actually go ahead and create this with the frame which matches our header view so we'll say zero zero and we can actually just paste this in here now we're going to want to go ahead and add this into our header view so we'll say add sub view for the chart and our chart data we want this to be chart data but specifically we're going to want it to be bar chart data so let's go ahead and create this up here this is going to be bar chart data is what i'm looking for like that and bar chart data you can create with a collection of values so you can use a data set which is you can have multiple collections of data sets i should say data set or data sets so we'll go ahead and create this uh data set so we'll go ahead and define this above it to keep it clean all right and this is going to be i believe you can do a bar chart data set and this gets created with the raw values itself you can see it takes in a sequence of bar chart data set let's see what else we have entries and labels so i'm just going to go ahead and use uh this first one here for chart data entry it's collection of this and essentially we're going to take our day data and we're going to compact map it to our chart data entry and it's going to be quite a few so maybe we'll need to change this but there's going to be x and y so let's figure out how we want to do this so the x should just be incremented so we move from left to right and the y should actually be the model dot count which is going to be the number of cases so let's see why this is yelling at me this is an integer and that is zero so this should be sufficient let's see what the error here is cannot convert value of into expected argument type of double so what we could do is simply cast this as a double and the other thing that i'm going to go ahead and do is instead of doing this compact map what we could actually do is create entries here so i'm going to go ahead and create entries up here which is going to be bar chart entry or chart data entry i should say or we can just use this it doesn't really matter and we're going to say for index in xero up until daydata.count we can go ahead and get the data from our day data at the given index and in our entries we are going to append basically a x and a y and the x is going to be the index and the y is going to be the data dot count once again casted as a double and i believe that's it that's all we need to do the other thing that we could do is specify colors for our data set and there are some presets that you could use here so i think there is a color style or something like that there is a let's see colors actually takes in a array of you know colors that we can pass in ourselves however there is uh presets that are available i believe it's either themes or colors or something like that so let's see if i can find what it's actually called so there's set color set color it's not what i'm looking for let's see if it's on the data itself we'll go ahead and see if there is colors here so we can go ahead and find what they are called it's either theme or style or something of that nature and if i can't find it i'm not going to kill too much time on it here i believe it is on the data set though let me just check the entries here so we could look for let's look for joyful because i know that's one of the ones that it uses and it'll be here so here is a collection and it's actually chart color template is what i'm looking for let's see where this is actually used all right chart color template we could use these directly but let's see so we're going to say the data sets color is going to be chart color template and let's see if it lets us do this it does not because this is count when we're trying to do colors and that's actually not what it is either and i'm of course not going to remember for the life of me where this gets assigned let's come into here and i'm going to look for colors so there is highlight color but actually before even i mess with colors a little too much i can look at the docs for this let's go ahead and give it a run let's make sure it's actually working so uh here we're appending the index which we also want to cast as a double like that i'm going to comment that out and give it a run and we'll we'll have a pretty big bar chart i hope at the top here so let's see there is our bar chart our cases started extremely high and they have gone uh you know pretty low which is a really good sign you can actually change up the axes here as well it's hard to kind of make out you know what it is looking like because there's so many bars there but let's go ahead and actually change the height of the header view here because we could probably make this look a little nicer so we'll say maybe divide it by 1.5 and we'll do the same thing for the actual bar chart view as well so let's come into here and we'll say the height here divided by 1.5 as well go ahead and give that a run and let's see i made a silly typo here let's see what's going on so we have cg wrecked and let's go ahead and line break this guy and let's see what's going on we have width and then we have height as well which we want to divide by 1.5 which should not be an issue so let's see why this is yelling at me all right value cg size has no member uh with view because i am making a silly typo so divided by 1.5 i'll just go ahead and do that and give it a run and okay that's looking a lot nicer now this right axes i don't like it i prefer just the left and the top but i do want to change the color here because it's kind of ugly without it so we're going to come back to github here and i like leaving this stuff in the actual video so you guys can actually see how i go about you know going through and finding stuff so we're gonna go to these demo projects and there's quite a few you know demos in here so there's a bar chart view there's a bubble chart view candlestick let's look for colored line chart and let's see if we have colors so it looks like we do have colors here let's see where they're being used all right so we have the chart we have a description we can set pinch legend we can customize the axes where is our actual colors being used so they're set up chart they're set value font and it looks like we're supplying the colors here for the particular uh data that we want to go ahead and use that's not exactly what i'm looking for so what i'm actually looking for is the template here so let's come back here and let's see if i can look up where this guy is being used so let's go ahead and read this so this is saying that we can actually use this somewhere and this basically returns a collection of these ns ui colors so it should let us actually supply this to the colors here so dataset.color is actually a collection of colors that we can supply so i'm going to go ahead and try to do this one more time so this is the array of nsui color oh it does let us assign to it okay i probably made a silly typo before so that is actually what we wanted but let's find a different type i think joyful looks pretty nice but let's go with i don't know it's a couple different ones in here let's try liberty and see what that looks like otherwise we're gonna go with a different one at this point i'm being nitty-gritty but that's okay that's the point of making our app look actually pretty nice that one's not the nicest looking so i'm gonna try joyful and look at that we have a pretty cool looking chart now we have a ridiculous number of bars so one thing that you might want to actually do is instead of using all of these um all of the particular data counts here what you could do is get a subset so we could say our set is going to be our day data dots we can get these suffix or prefix you know we can get the most recent maybe 20 values and we can go ahead and use that instead of using the entire array so here we would just use the set instead of the entire day data at this point we would only have 20 values now we're actually plotting the values above it but the bars are much smaller which makes it look a whole lot more legible as well as just like nicer instead of having ridiculously tiny bars personally i'd probably do 30 and then i probably hide the values so let's see if there is a way to hide the values on here i think there should be so let's see hides values is what i'm looking for or shows values something like that let's see if i can find it in the next 30 second so chart i know you can configure a lot of the grid background and grid lines and all that stuff there's a lot of things you can configure in this framework which is why i'm kind of all over the place but i mean at this point we're all over the place so whatever so looking for value colors value fonts there's value text color so what we actually want to do is not show the values so we can look for hide and i can't seem to find it so i'll probably just wrap it up here for the sake of everyone not getting a headache with me jumping around so much but that's all i've got for you guys today i mean this is a pretty pretty good bare bones coveted tracker app now what i would do is first of all let's go ahead and test this let's take a look at alaska's cases and uh let's see if things actually changed so it looks like the topmost value here is 5 57 000 actually which aligns with uh may 7th here and uh here we have data set as the label which is not really what we want we could change it so a couple things that i would recommend here i would get rid of the top axis the right axis i would maybe animate this chart i believe there is an animation mechanism built into this framework and what's also really nice in this framework is there is a like different kinds of charts so i really like personally the bar charts here but this one's pretty cool too this like uh line chart but it's like filled in so you can make this look really really nice you just have to spend time with it um and yeah this is how filtering works now we're way over time so i do not want to spend more time and add a way to filter out dates but if you want to take it a step further and want to share it maybe i can give you a shout out here on the channel this api does give you um the ability to get data based for a single day so if you take a look at the url endpoints here it actually just has you pass in the date you care about so maybe you can actually go ahead and make these rows tappable and when you tap into it you would get more information about that particular date so that's all i've got for you guys today super long video i've been doing shorter videos lately and i've wanted to make an actual app and just make something longer on the channel if you enjoyed the video drop a like down below if you watched until the very end kudos to you i was all over the place subscribe to the channel if you're into ios want to stick around thanks again for watching i'll catch you on the next one you
Info
Channel: iOS Academy
Views: 3,937
Rating: undefined out of 5
Keywords: swift build app, swift tutorial, swiftUI, swift 5, swift how to make app, learn swift, how to make app, covid app, swift make app 2021, swift 2021, tutorial swift, swift learning, swift ios app, swift tableView, swift charts, swift graph, swift make app, swift 5 tutorial, 2021 swift 5, swift animation, swift for beginner, swift basics, swiftUI beginners, swiftUI basics, swift tableView custom cell, swift tableView tutorial, swift how to make an app, ios app, tableview
Id: MyYV65boqec
Channel Id: undefined
Length: 65min 24sec (3924 seconds)
Published: Sun Jun 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.