Build A Weather App in SwiftUI (tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
um y'all seen this weather app i just built in swift ui pretty nice right and i'm gonna be showing you how you can build this at yourself i've broken down this tutorial into five sections we're gonna be building this header then there's this daily view where it shows us the forecast today followed by an hourly forecast list a horizontal list next we have this little section for the details button and lastly we have a weekly forecast view and i thought about how i could remake my tutorials to make them more engaging and just easier to follow more concise so i've added sections in the timeline of this video where you can jump around to the section that you want or just watch the whole thing all the way through up to you and in this video we're not gonna be hitting a live api there is a part two in the description though if you do wanna learn how to hook it up to open weather api in this case you can check that out as well as a bunch of other tips that i give on my experiences with swift ui as well as all the project files the designs and code real quick part two is gonna be ten bucks that's like three cups coffee if you wanna support me the channel if you enjoyed this tutorial i think you'll really enjoy that check it out and now back to the video and this video is meant to be for beginners and intermediate devs so swift ui hasn't even been around for that long so i feel like we're all beginners in a way and there's so much to learn and after you finish watching if you enjoyed this video give it a like and subscribe to the channel where i make more videos like this and software engineering in general that way you never miss out so i'm done with the intro let's open up xcode and start this project alright one last thing any feedback for me on how to make my tutorials better or anything else drop them in the comments or feel free to dm me on twitter or instagram all right let's jump over to xcode for real now and start this tutorial [Music] all right real quick we're in xcode you want to create a new single view app here i'm just going to call this weather app for this identifier just type in com dot your first last name just needs to be unique click swift ui make sure all these things are configured and you can check include unit tests because we might write a few once you're done just save this somewhere and now we're in our content view so before we start coding i just want to go through a few shortcuts that i'm going to be using throughout this entire tutorial first one is command shift o so if you press that you can open something really quick so if i start typing info.plist it's going to auto complete and i can jump back to it or jump to it really fast now to go backwards uh really quick i have a keyboard shortcut set for command opening bracket and that's going to quickly allow me to get back to my previous screen another really helpful shortcut is shift command j and what that's going to allow us to do is see where for example if this folder is collapsed and i'm inside this file what it's going to do is show me where i am inside my project so you can see that this file just folder just opened up and i'm in my content view another useful shortcut is sometimes we're going to be making changes to our canvas here for example i'm going to just paste this three times and wrap this in a v-stack you don't have to do this but just to illustrate this point right now it's updating right away but oftentimes it's gonna give you a little button here that says resume that means canvas has stopped automatically refreshing now to you rather than clicking this button every single time what you want to do is click option command p and that's going to automatically refresh canvas we're going to do this doing that periodically you'll see that canvas is just going to stop refreshing and that's like probably the number one shortcut if you're going to remember one remember that one this last one is going to be the object library so if you press shift command l you're going to see that we have all these modifiers we have all our views our views are the building blocks for applications you can think of them as all the labels the buttons this navigation view picker everything here it's documented it kind of shows you how to use it with an example really fast modifiers are things that allow us to customize our views so these are our views modifiers allow us to customize them and again you can read all about the different modifiers here you'll probably just learn most of these after just using them for a little while so as you're building apps doing more tutorials etc you're just gonna learn uh how to use most of these so i wouldn't worry about memorizing any of them here is a little section where they give us some snippets that we can use so these are really useful if you don't want to repeat yourself a thousand different times you can just open shift command l and just click one of these snippets for example if i come up here and say i want to create like a new struct i can get the template for that really quick that's the big one so this object library is really helpful obviously here we can add some assets which we're going to be doing in a second here any colors we've added in our assets a lot of cool stuff here um we're going to be using that a lot going over the project structure real quick so we have this content view this is our main view that swift uh the swift ui project gives us and here's gonna where you'll see like the bulk of your views you can name this whatever you want it doesn't have to be content view but rule of thumb is whatever you this file is called it's what we want to call this struct that we have and the next one's our asset catalog and this is where we're going to store our colors our images mess around with that later and for that key list this is where we have a lot of the configuration settings for our project so some of the big ones that i can think of is like product names just your app name um we have like versions here a lot of cool stuff um we won't really have to worry about this right now but when you're submitting this the app store becomes more and more important and when you add like permissions so you want to access somebody's location or photos you want to add that stuff in here so back to our content view the other file you're going to see here is this weather app so this is like the main entry point to our application it's new to swift ui 2. you can call it ios 14 but basically rather than an app delegate we have this new weather app app so kind of called this maybe we should just call the weather rather than weather app because we get this app appended too that's that's good to know but we get this body and basically this is our content view uh another keyboard shortcut here so command click and you can jump to definition and now we're back at our content view so here's where we're going to be creating our first view and if we look at the design it is this header view so what we have here is when you're thinking about making views in swift ui you want to think of everything in stacks what i mean by that is you can see this text and this image they're kind of in a horizontal like squares you can think of it so we want to kind of create that and swift you odd and the nice thing about that is we have a tool that we could use and it's called an h stack so we're going to be doing that right in here for now we're going to just type h stack and this is the horizontal stack that i just showed you or that rectangle that i just drew similar concept and inside here we want some text because we had that title and we called that weather forecast i'm just going to copy it just like that and under that we had an image so we need to add this asset into our project now so what i'm going to do is provide this for everybody you can download it in the description shift command o we're going to go to our asset catalog this is the fastest way to do it and i'm going to drag in that image so you can see here i dragged in this menu icon and it's a pdf the one thing we need to do all pdfs is select a scale and we're going to do single scale that just basically means that ios is going to scale this pdf for us depending on the user's device which is really important and inside here all we have to do is just call logo or i called it menu dash icon all right so after everything refreshes now we have our text next to uh our image here the one thing too is that this image needs to be selectable so it actually needs to be a button and we could easily do that by adding a button here then we get our autocomplete what we want to do is select this one that has an action and for now we're gonna add an empty closure and for our label we're going to put in our image inside of here if you want to easily format this is another keyboard shortcut so it's believe control i uh i have these mapped to different things so i think the stock keyboard shortcut and xcode is control i and it's going to indent everything for you last thing we want to do a little cleanup so we like to use trailing closures whenever we can so what that means is we can get rid of all this extra verbose stuff and clean it up so now it's a lot easier to read and it succeeds so now we kind of need to make it look like our designs here delete this we have some space here we have some white space here and that's really easy to do so we have this h stack here and to add some space between our button and our text here we just want to add some spacers and we're going to add one more after here you can see it looks a lot better now so that's our header that's our first view that we just created so congratulations this is your first project that's your first swift ui view and we're going to be moving on so the next one that we're begin building out is this one this is just like today's forecast and to do this we're gonna need to do a little setup work so we're actually gonna be using an api this api is called openweathermap.org so what you want to do is navigate to this website when you get to it you're going to want to create an account so you can see i'm already signed in here once you create an account click on this api tab once you click the api tab click on this one one call api and just click the docs so you can see this is the api for retrieving current weather minute hourly daily forecast yadda yadda and they give you an example here of one request that you can create and the things to know here what we need to do is pass in our lat are long any part of this api that one we want to exclude for example if you didn't want the minutely forecast you can type middle minutely here and exclude it and last but not least you need your api key which is in your profile under my api keys once you navigate here you're going to see your api key all right so let's just take a look of what an example response looks like from this endpoint if we scroll down we can see that they give us one here this is the latin long that they plugged in and looks like we get the current forecast hourly and you can see they truncate this so this isn't like real json that you could use and we need real json for this to work so this is the second part of this video let's get the json for this endpoint all right so we've made some progress here we need to get this json and to do that we're going to be using http client one of my favorites is called paw and to download paw you can go into the description and get it through set app set app is like netflix for mac apps they have a bunch of different apps that you can get with just one subscription kind of like netflix and if you want to follow along with this portion of it uh download setup download paw use the link in the description supports the channel and overall like i subscribe to this thing it's really useful has a lot of cool apps and back to the tutorial all right so i've set up open i'm going to search for paw and gonna click open there's a keyboard shortcut which is command n which is new project and there we go so pause open a lot of cool things with paw the main thing that you want to do is just uh create a request here and if we jump back to safari we have a request or an endpoint here that we can hit so what you want to do is just copy this and paste it into paw you can see it automatically fills in the parameters that we need to supply this is really cool uh another cool thing with this is that it generates you code for like swift code or any language for that matter a bunch of popular frameworks so you can see it this is what the alamo fire code would look like this is a popular networking client for swift moya is another one you can see this is what the code look like and we're gonna be using this in part two of this basically and copying it so if you don't have paul like i said download it link in the description really useful app here there's headers that you can supply more url parameters if your request has a body if it was like a post request for example notice all the keyboard shortcuts here you can easily go through all these but back to this so let's supply a latin long for this i'm going to be using boston the next part is what we want to exclude let's just type in alerts last but not least you want to plug in your api key here and again you can get that in safari under my api keys once you've logged in main account yada yada so just like that and i spelled alerts wrong so this should be alerts and then all we have to do is click enter and this is going to make the request for us as you can see this is all the data that we get back from this endpoint we have our current forecast here minutely hourly daily and this is our that long a few other things here if you wanted to see the json version of this we can toggle json text i believe yeah there yeah so this is like what you're used to seeing if you're making a request everything in this json view i kind of like this view here just json i just feel like it's easier to read for me the part that we're going to be using here is this current section so current is like today which is what our design here is calling for so we just want to see what the weather is currently it's going to give us a forecast today we're going to need to get the date for today the location which is going to be fun and we have like an icon here which is also going to be a little tricky so once you have your request and you've called this however you did it if you used paw all you want to do is click json text and we want to copy this response like i said in part one we're not gonna click we're not gonna hit the actual live api that's for part two so we wanna copy this and we're gonna be using it as a local data source so i'm gonna copy this and jump back to xcode inside of xcode another keyboard shortcuts option command n this is going to create a group for us let's just type in api here and now under api we're going to click command n which is a new file and we're going to search for empty so empty here click enter i'm going to call this something called this weather response dot json inside here all we want to do is just paste in that json if you don't have this and you didn't follow the last steps of making the request yourself you can download this from the github i guess that i'm going to post in the description so you don't need to do the other stuff if you didn't want to you can just copy this create a new file a new directory new file and just paste it in and you'll have the same stuff that i have here and this is like basically the starting point for that next part of this is how do we get this data into our view we're going to be creating a new file for that actually let's make it an api so make sure that this directory selected click command n and this is going to be a swift file and let's call this weather service all right so this is a swift file we're going to do is create a class and inside of this class we're going to create a shared variable so this is going to mean that this class is a singleton we only want one instance of it so once we've done that we need some kind of function that is going to read our response that we have here and another thing that we could do is we can look at this side by side if you click option then click on one of these files it's one way of doing this the next step before we continue is we need to get this json into a model object now to do this it's a little tricky uh there's a few ways we can do it we can go through and create a bunch of structs in swift that mimic this json response that is very time consuming because you can see this response is giant there's a lot of properties yadda yadda just don't have time for that part of being a programmer is that we're lazy we don't want to do this ourselves so what we're going to be doing is using a tool called quick type in order to generate uh some swift models for us that mimic this api response now this part you don't need to follow along with because i'm going to do it really fast if you want to follow along watch this video on like 0.5 speed or whatever because there's kind of a lot going on but i'm going to do my best to explain it but really fast so first what we want to do is open up our command line i use item but whatever you use you want to open it now once that is open let me just make it a little bit bigger what we want to do i'm going to cd into our project here i called it weather app so i'm inside my project inside of here what we're going to do is say we want a brew package so the first thing we want to do is install quick type if you don't have it you want to do brew install quick type just like that i already have it but if you don't just click enter it's gonna install i already have it like i said uh so i'm just gonna get rid of that so we're in our project directory um and we wanna run this command so you want to quick type and excuse this autocompletes uh but basically we want it to find this json that we just added so if we go back to xcode real quick this json right here which is inside a weather app api and we called it weatherj response.json so what we want to do is say slash api and inside of here we just have one file which is our our two files but we want this one weatherresponse.json now we want to say the language that we want to use is swift uh our output file which is dash o this is going to be weather app slash api and we're just going to call this api dot swift a few other things we might want i'm going to open up a new tab i'm going to type in quick type you can see i already did this on a different project and we want like a bunch of these fields basically um to do to find like the actual fields we can do quick type help or dash help and dash h there yeah all right so there's a bunch of options that you can give quick type to generate your code for you and the few that we want here are going to be we have o which is our output file we have l for our language we're going gonna want no enums uh the next one we want is when we scroll down to swift we want just types dash dash just types the last one we want or maybe last one i'm not 100 sure we want swift 5 support and i think the last one would be initializers okay we don't want any want any initializers and i'm gonna click enter and if you didn't get any errors here it probably worked so copy this type it in you're inside of your pro like this is where i saved my project so make sure that you're in the proper directory if you're following along you don't have to do this like i mentioned but if you want to uh type in this command and click enter once you do that we want to right click on api and we want to click add files to weather app we're going to click the api.swift [Music] and just like that look at this we have all of these models that were just generated for us like how cool is that just imagine if we spent all this time doing this ourselves it could take a lot of time so this is awesome i highly highly highly recommend to generate code as much as possible so let's jump back to our weather service and in here on the other side let's open up our api.swift so i'm going to click option click then here this is going to be our weather service so now that we have our models here what we want to do is create some kind of variable to access that json so we're doing all of this just so we can read that json so what we're going to do is just say json i don't really have a great name for this um call it json we're going to call this api and it's going to be this top level model so now what we need to do is decode this data so we're going to create a decoder and basically all we need to do now is just find a path or url to this json data and in order to do that we need our bundle so let's say url equals bundle dot main dot url this is gonna be for resource i called my file weather response.json okay all right so now we want to retrieve this data and in order to do that what we want to do is say data equals data then we should well we should have an initializer here that takes in a url i think contents of url here we go we're going to force unwrap the url now we have this data that we need to try [Applause] we're going to get an error here because we need to force unwrap this there yeah so now we have our data uh now we need to take this data and turn it into our api model all right a lot of this is kind of annoying stuff but we're going to take our decoder again i think we need to try here and we're going to say decode what type we want to decode our api we have to type himself here because that's the type and we need to pass it some data so just like that if everything worked okay so the last bit of this is saying that our struct here does not conform to decodable now one thing that we can do is just add codable to all these models but i'm too lazy to do that let's jump back to our command line here and what we want to do now is modify this a little bit uh again if you didn't run this script just copy this from the gist in the description i forgot to say that so you don't have to run this but let's just get rid of that and click enter so we're just running language swift output file our same output file no enums swift 5 support initializer so we got rid of the just types and if we go back you can see we have codable right here so do command b and again i forgot to mention this i'll put a flag right before everything happens uh if you don't have this file go in the description and just copy it and just paste it into a file called api.swift sweet if you've got this far congratulations um this was like a lot of work but you can see it paid off because we didn't have to write any of this code now we can access all of our weather json that we have here and we can access it in swift so we have it here um perfect let's jump back to our content view and here is where we're going to be building out our second view so i'm gonna get rid of this section here if you click this x it should go away and we're back so in order to build off this second view here um it's a little bit more complex we can see that we have like another stack we have this on top of this so look at this blue outline box we can see that we have this text above the today text above the date text here and then we have this image so we need to create some kind of h stack but you can see here we have something on top of something which means it has to be in a v stack so it's gonna be a level of nesting icons how are we gonna get these icons into the project uh the nice thing is apple gives them to us for free uh we have this thing called sf fonts or sf symbols and inside of here there's a section for weather you can see that we have all these beautiful icons now there's a lot of stuff here and we need a way to kind of take the icons from our sf symbols and use them in our app to do that we're going to be adding one more json file to our project this way we can easily look up what weather icon we need for that particular condition that is in our weather response so let's add this now click command n we're going gonna be searching for empty and here we are going to be adding a new empty file so here let's just call this icons dot json okay this you're also gonna have to paste in i'm not gonna go through this too much but it's just a giant json response all right so i've pasted this in like i said uh get this from the description below but it's just gonna allow us to look up what icon we need based on its code which is this key right here and then it's gonna give us some kind of icon which is a fs symbol so you should have a bunch of things in your api folder at this point if you don't have this stuff just go into the description and copy it you can copy this you can copy this you can copy this this we just made um another thing we need to do is now is access the icons somehow so this is going to be pretty easy and we're going to do the same exact thing basically and call this icons uh so one thing we need to do is create a struct for our icons so it says struct icons i recall icon naked of type codable then if we look at our icon we have a label and icon uh okay better name for this is and call weather symbol and we have one property which is icon which is a tip string the next one is label now this type that we're gonna assign this variable is going to be of type string and weather symbol just like that we're going to change our file name so we call this icons and for decoding this we're going to dictionary says string and value is going to be weather symbols it should be something like that now if all this said and done works we should get values out of both these variables how can we test this how can we see if this actually works so one way is we can access our shared service from some content view and just see if the app doesn't crash by like running it on some device that takes a lot of time so let's just write a quick unit test on how to do this or how to test this is what i should say we have one function here and we're just going to call this test responses uh what do we need we need our weather service [Music] boom we have it we need our icons and we're testing our other json so let's actually do option and click on our service so we have that side by side the big thing that we're testing here is let's see icons gross weather service dot icons the last thing we need is our json we're just gonna test both these here okay so the actual test that we're writing is we want to make sure that whoops all right so once we have these things we can just assert and just make sure that they're not nail or that they don't throw so let's just do both so i can show you both these examples so if we start typing no throw all right let's use not nil so the first one is going to be not nil inside of here which is passing icons then the next thing that we can do is just say no throw and [Music] here we just pass in json so essentially our test is going to fail if both of these assertions are false we can click this play button here that's gonna run our test suite all right just like that you can see we got the green check mark everything is correct everything passes no errors if you have some kind of error here then something's not right with your response like your data does not match what i have so if i navigate to weather response something isn't right here like i said you want to copy and paste this to make sure it's one to one with what i have or something might be messed up in your models maybe something's off here you can copy it correctly if you ran the script yourself maybe you missed something um we want to make sure that both this test passes because that means our data is correct all right we're going to pause here this is a lot of stuff so i just taught y'all how to access local data how we can decode the data which is really important awesome skill to have um we did that again a second time and we just learned how to write a test so i hope you're learning a lot up until this point so we just wrote tests we created one view uh we created a weather service a lot of cool stuff you see how involved like an app gets all these things you thought we were just gonna be building out the ui but now we need the data somehow and if you're enjoying it up until this point drop a like on the video the last part of this is going to be building out all the views so we did a lot of setup work here to get the data uh to make sure it's correct to make sure that we can use it now let's build out the ui so let's get back to coding okay so we're back in the content view and now let's actually start building out this current forecast view and to do that we're going to be creating a new file and let's just create a new directory too shift command n we'll create a new group and here let's just type views then command n to create a new file this is going to be a swift ui view let's call this current forecast view all right so once you've gotten this far we can look at the design and like i mentioned we have two labels here so one that just lets us know that this is today's forecast with the date we have an icon we have the temperature and last we have the city so let's start out building this section here we're gonna need some kind of stack in h stack we're gonna need an image and we're gonna need another stack for these two labels because they're vertically uh one on top of the other everything in this view is kind of laid out vertically so here we have one label on top of the next then we have this little section here all laid out vertically so jumping back to our current forecast view let's create a v stack this is going to be our very outside view inside of it we're going to have a h stack and this is going to be that top section so in that top section we had an image and for now let's just use a system image so we can start typing system and just type cloud next we're going to create a v-stack inside of here we had two texts so the first one said today then the one below it had the current date i'm just gonna copy that notice this format so it says fry07jn so we're gonna have to figure out a way to format our date or we'll get to that a little bit later so you can see just like that we kind of have the basics of this first part let's move on to this one then we can kind of wrap it up and style everything at the end so we're back in our v stack here this is the outermost view and here we're just gonna have a text and it's gonna have the temperature so let's just type in 32 then to get this temperature sign i believe it is option zero and just like that shows up last but not least we had another text and i'm just leaving a little bit of space between these just so you get an idea of the different parts of this view um the last part of this had the city so just type in boston mass or type in whatever you want but this is where i live so just like that we kind of have the skeleton of what we have here now we just need to style it last we need to actually show real data live data that is from our json so it's kind of style everything first we can move back to the design i'm going to be doing this a lot and if you want this design to kind of follow along with what i'm doing like i said there's a part two to this video if you end up getting it you kind of get everything all together so the code the designs uh a video for the part two um so up to you but anyways but this outermost v-stack that we created has a shadow has rounded corners um and that's pretty much it so if we look at the drop shadow you can see that we have a blur four and a y offset of four and we have corner radius so let's apply that [Applause] now this looks a bit funny you can see that the shadow is applied to all of our views what we need to do is give this v-stack a background color now this didn't fix our problem so what we need to do is sometimes these modifiers have to be applied in certain order so let's actually move this to very beginning you can see that we get our shadow so big thing you notice right off the bat is the size of this thing it's kind of small so you kind of want it to stretch and fill like all the available space and give the height some kind of height that matches our design so let's first make it stretch across and we can use this frame modifier we can get a width and here let's just start typing infinity so this just makes means stretch all the way across and if we look at our designs this card has a height of 200. you can see that the width is still a little bit messed up so what we can do is actually use the initializer that takes in a max width then we can also update the height to max height you can see that it's starting to look a lot better now one thing i want to point out is how harsh this shadow is it's because it doesn't have an opacity so let's add that we have this color parameter here so we can use the default initializer for color inside of here we can use this initializer with a color space then we can just do rgb white let's do zero then opacity we can do 0.15 and you can see that's starting to look a little bit dimmer it's still there let's just see what our designs call for so yep 15 just like the designs and if you want it to be a little bit heavier you just update the opacity to whatever you like and that looks a little bit more better in my opinion let's just keep it at 25. all right so let's move on to styling the text so this is pretty easy if we click on the text in the design we can see that it's medium and it's size 16. so the modifier for text and again if you do shift command l you can kind of look at all the modifiers we have and if we start typing font we see that we get a bunch of different modifiers here so we won't wait so we want to give this font some weight and we want medium just like that then the last part is that we just need to give it a size you should be able to just type in font and we have one here for size which takes in some kind of size and we just want to type in 16. now the next one we have here is the temperature so for this one we have a color which is yellow we're just going to go with that for now so it's light and it's size 80. so let's copy these two modifiers then last we just need to give it a color so we can start typing foreground color and this is going to be yellow the last two labels so see this one has like a lighter gray color it's medium of size 14. so let's just copy this then last but not least we have today which is medium of size 18 and let's also apply a foreground color to this before i forget so it's just typing gray and today this was size 18. it's starting to look a lot like our designs you can see that these two labels here they're kind of centered and we want them to be leading so that is an easy fix so this v-stack should have an alignment and i probably spelt that wrong aligned mint and now we just want to select leading you can see that it shifts over kind of match the entire design that's pretty much it you can see that there's a little bit of padding here so it doesn't fully go all the way to the edges but don't mind that when we actually import this into our content view we're going to add the padding at the very end so the next thing you might be thinking is okay we have this beautiful view but how do we actually get real data into it so that is when we have our models that we generated so we have this api.swift and i'm just going to click option and click on that file so we don't need the canvas you can close that out by clicking option command enter so now we kind of have these two files side by side we already look built out the view looks great we just need to actually give it some real data so like a real date here a real temperature and a real location so when we look at our response that we get from the json that we have so we have a weather response let's scroll up to the very top we have this current model here so this gives us a date time which is going to be useful for getting the date we have a temperature the location in the form of latin long we're gonna need to figure out a way that we can take these coordinates and look up the actual city uh yeah so that's basically just like what we have to do so how are we going to do this so looking at our models here we have this current model which is going to have all our data in it if we take a look at it we have this date time we need to convert this integer which is a timestamp into an actual date so to do this we are going to first create an extension on api so let's just create a new file usual file and let's type in current plus extension and click enter so i'm going to go back and i'm actually going to make current plus extensions on the left over here there yeah that way we can just look at things so we're going to create an extension on current [Applause] and inside of here we need to do a few things so the first and foremost we need to get this date so let's create a computer property for that we say formatted date it's going to be of type string so how can we get this we have this date time which is a time stamp so we need to take this time stamp and convert it into a date so we do that by using initializer on date which takes in a time stamp and we can pass in daytime here so in that now that we've done that we need a way to format it so you can see that we need to actually make this the time interval first so we can create a formatter and just call this df for date formatter then this date formatter needs a format you might be wondering okay that's great what is this format let's come back to that in a second so once we have this format um what we can do is ask our date formatter to format this date so all that looks like is want to return a string from date and just like that we are done minus this format so to get this format what we actually want to do is hop over to safari and i'm going to show you a trick on an easy way to do this all right so if you open up safari and go to this website here nsdate formatter you will see that we can supply some kind of format string and we get result here so all we need to do is just make this match our design that we have here so we need the day then we have the day of the month and followed by the month so to do that we can kind of look at the examples here you can see there's one here for day so that's e then next we need the day and the month and it looks like we can just do d followed by the month so we don't need year so that's all we need right here let's copy that and jump back to xcode and paste this into our date format the next thing we need to format is the temperature if we kind of go back to our response we can look at our data here and the temp is kind of weird so when we look at the api documentation we kind of want this in fahrenheit's and if you want it and something else you can follow this step and get that result so we can see that we have this optional parameter it's called units if we keep reading it says standard units will be applied by default so what we want to do is change this to imperial that way we can get fahrenheit so let's open up paw inside of paw what we want to do is just type in units and here's going to be imperial now if we take a look our temperature response you can see that so i'm going to copy this response and if you're following along at this point uh just crack open paw add this parameter change it to whatever you like and copy the json if you don't mind having it in standard format like we have here just keep it the way it is but i'm going to change this to fahrenheit so i just pasted in the new json so now we have that the one thing we need to do now is just format it so let's type formatted temp it's going to type string inside of here all we have to do is just create a string this is gonna be temp and we're gonna be adding in the little symbol if we go back to our designs we can see that we have those two things covered and the last thing we really need to do is figure out how we're going to get this city so like i mentioned before we have a latin long inside of our response so how can we take that and kind of make a city out of it and look up like what city that is and we can do that with core locations so there's actually a functions at a core location that will look this up for us we just have to supply some coordinates and it will do the rest for us all right we're going to come down here we're going to create a new function this can be called fetch city and the api we're going to use is really easy so if we start typing geo we want this geocoder we're going to initialize it and now we need to find the correct api so i believe it's this one here takes in a seo location and it's going to give us back hopefully the city so for this location we can initialize a new one and here we can pass in our lat and our long and click enter here so we get an array of place marks and error just like that so if you build your project we're gonna see that we have a few errors here and this is because we can't find this latin long in scope so we're going to be taking this function we want to copy it and we're going to put it inside of our weather service just like this so inside of our weather service you should have everything here we're going to need to import core location now if we build this we have a few more errors so it's still saying you can't find latin long what we need to do is say [Music] json.json.long and now you should get build success if you click command b and what we want to do is kind of map over place marks we want to get the very first one and this is going to be a cl placemark object which has a lot of different properties basically on what it thinks this location is what we want to do is because it's optional it's a flat map over it inside of here what we want to do is just return a string so the first part of this will be the locality and this is the city associated with this place mark so if you read the description that's how i kind of know how to use this now we have a space or we have a comma in a space and next we have the state and i believe that is administration area you can see that in the description it says right here state your providence so we're going to use that now see we have an optional string here it's kind of make it non-optional and just type in error so if something went wrong we'll get it we'll just display error now the last step of this is how do we communicate this back to our current forecast view our current yeah forecast view i had that right so here inside of this view we need some way to kind of get this city that's inside of our weather service and to this text here now i'm going to close this for a second in order to be able to achieve this we need to use some kind of framework to communicate changes back to our ui and that framework is going to be combined so combine is a framework that's a reactive framework which just means when things update kind of notifies its subscribers and we can start typing combine and we want to make this weather service an object so if we start typing object [Music] we can use this now this protocol requires one method and that's what object change the type of object that we're going to be using is a pass-through object which is like the most common one or pass-through subject it's generic so what we need to do is just apply a string here and we can supply never for the error parameter so something goes wrong and then we just need to initialize this so this isn't a tutorial on combined because this framework is very extensive but essentially what we're doing here is we're making our service an observable object that means we're going to be observing some change that changes when we try to fetch the city so once we do that we're going to get a city and we need to notify our view that that city exists so i've said that like twice now hopefully you understand what's happening and we're gonna do it by the means of this past three subject so to get this city out of this closure here we kind of want to make a variable up here and which we need to use a special variable though so this can be published our city and let's assign this to an empty string actually let's just type loading here that way we can give the user some information if this takes a really long time so the next thing we need to do is just update this property so we can come down here and just type in self [Music] dot city we can assign that to city and the last thing we need to do is send out a signal to our view that it should update and what that looks like is if we say self. object will change then here what we can do is send this expects a string so we can just send city just like that you can see that we have a warning here and that's because if we click on these we can see that they're optional so that means that they could be nil and what we can do is just use this optional operator here and it's just passing an empty string if it's missing now we kind of need to hook everything up right so we have this fetch city function let's jump back to our content view and we can pull up canvas here before we add in our new view that we created let's actually take a look at it one last time and what we want to do is add a few properties here to our strut so the first one being current and this can be of type current and we have a city so that's city of type string [Applause] so the reason why i chose to do these is again this is our model that's representing our data from json we have this object that we created that we're going to be using so we need that in our view so what we can do is now replace this with current dot formatted date the enterprise replace the city with city and i can't forget about the temperature so we want to use format attempt just like that last thing we need to solve is one this initializer is going to complain um let's come back to that we need to solve our icon here so we forgot about the icon really let's kind of fix that so we need to kind of add in the proper icon if we jump back to our file that we created here for extensions what we can do is make another computer property and this is going to be icon name what we want to do here is get the icon name so this can be icon name again and it is going to be weather taught first dot [Music] icon so this is optional so if it doesn't exist let's just use cloud then now all we need to do is get our icon out of our dictionary so we have a dictionary inside of our weather service which is here and our dictionary our our weather service here is a singleton so you can access it from anywhere so you can say weather service dot shared this would be icons then let's look for icon name this is optional so it may not exist [Music] by the way which is fun and we actually don't need this optional here so if that doesn't exist let's just return cloud as well and lastly i just forgot to access the icon here alright so now we have the icon name let's jump back to our daily forecast view and update this last property then i'll kind of show you how everything comes together so we get another build failure here so this is like the very last step and that is because we added these two properties up here at the top and we just need to pass something in for the preview the cool thing is we have this singleton for our weather service so we can actually access it we have our json inside of it and we have this current model just like that last blonde last but not least we need some kind of city so let's type in boston mouse all right so we're here and we see that we have this preview cannot preview in this file and it's a weird error um i just kind of fixed it so let me just go through what i just did so if you remember a few minutes ago we added in this brand new response which had um the temperature in fahrenheit when we did this it kind of broke our api.swift so it didn't really match so what we need to do is generate it one more time and again if you never generated it from the get-go just copy this from the description or if you already did copy it from the description it's probably already up to date you didn't really have to and if you copied this from the description it's already up to date so you wouldn't have to kind of switch it over like i just did but if you were following along and generated this yourself you want to jump to your project in terminal or item whatever you use so i'm here in that directory and we want to run that quick type command one more time and before i do that so how did i find this error so if we go to our tests our tests were passing so what we can do is run them again so our test crashes because of this decoding error we can see that minutely was parse number does not fit an end so you can see that's obviously not an integer this is a float or a double so what we need to do is fix it so this is like the beauty of tests your tests will always catch these things like that so you should be writing tests and you should be running them often and how we can fix this is and make this test pass is if we jump back to terminal what we want to do is just run this command again and just like that it should have updated our api.json and if we run our test suite it should pass there we go so our test passed just like that and now let's jump back to our view and there we go so we have our temperature here the last thing we want to do is kind of make it a whole number we don't want this decimal so that's easy to fix if we jump to our formatted temp i just wrap this inside of an int now we can jump back and sometimes you have to build it then refresh canvas so that's fixed the last thing is is this location so in order to fix that what we can do is jump to our content view and now is a good time for us to add in our new view that we just created so we can start typing current forecast view then this takes our current model so what we can do here is create a constant for weather service and we can just assign this to weather service dot shared and we're pretty much going to be doing the same exact thing so access our weather service and this is going to be the json and current just like that and now we need some kind of city to pass in and we already created this city on our weather service so we can just access it just like that so the first thing is that this weather service has to be an observed object and again we have this special modifier that we can add it fixes our error and we can actually see our view but it's not looking too happy so what we need to do is make everything inside of a v stack so we kind of want to paste this below and format it and now let's wrap everything inside of v stack then we can just indent everything so now it's starting to look a lot nicer we can fix the spacing later um for now what we can do also is just add some padding and that's gonna kind of give us some margins on the sides so you can see that our city right now is a little messed up so it's stuck at loading and it's because we need to fetch our city so to do that we're gonna start typing on appear inside of on appear what we can actually do is get rid of these brackets just ask our weather service to fetch the city now this part of it is not going to work inside of canvas so canvas doesn't really do any api calls what it does is it's really good at showing static data via the previews so in order to actually see the real city let's run this on device alright so my device loaded and if you've been following along this whole entire time you should see something like this so we were able to fetch our location from our latitude longitude we have our temperature here and everything's starting to look really good now looking at the simulator the one thing that looks off for me is the fact that it's cloudy right now and let's just make sure that this icon is what it's supposed to be so if we jump back to our extension file here what we can do is jump to weather and just take a look at this and i believe instead of the icon name what we need is the actual id for the icon because remember we added in this lookup table where there's an id that we kind of search from i believe that is the last thing we need to do in this view will be finished so instead of icon here let's type in id then it needs to be a string and the default id can be 200 and once that's updated what we can do too is use the filled version of this icon so fs fonts provides us two versions of the icon there's one that's kind of outlined then the very last one is filled so all we have to really do is tag on dot fill at the very end now if we jump back to our content view instead of this outlined one we should get filled alright so that looks good i'm looking at our designs again and we forgot to make this yellow so let's go ahead and change that all right so now this view is finished i know it took a little bit of time but the rest should be a lot easier because this is the process that we're gonna have to go through so when we build out our next view which is this horizontal list i'm gonna go a little bit faster and also this one's a little comp little less complex there's only three things here um the list is a little bit different so we haven't messed around with that but overall it should be pretty simple to do then we have the very last two as well all right so we just finished one of the major views in this project and after this it gets a lot easier so this one was the big one and i hope you're starting to see how things are clicking how we can take api data and kind of massage it get it all the way into our view going forward i'm going to go a little bit faster i'm not going to really go over every single step but it's all pretty much the same stuff and if you're joining up until this point and you haven't yet drop a like on this video all right two down three more views to go let's get back to xcode all right so now we're on our hourly forecast if we jump back to figma we can see that we have this collection of cells here and inside of each cell we have a label we have an image and we have the temperature so this should be pretty straightforward the one thing that we need to look out for is one how do we make a list that scrolls horizontally and two as you can see the very first cell is selected indicated by this yellow background color so that's gonna be a little tricky as well all right so if we jump to xcode let's create a new file and it's gonna be swift ui view we can call this hourly forecast view [Music] and here let's start really basic so this view for the most part is pretty basic so we're gonna have a v stack [Music] which is going to have some text we're going to have an image and for now let's just type system [Music] and we have some more text [Music] so we need to style this a bit and also let's just for now delete these placeholders and add in some dummy text so we're gonna give it some spacing and let's do 25 here the next thing we want to do is add our shadow corner radius we need a way to be able to set the background color because the very first cell is going to be yellow all these different things so do background do color.yellow [Music] and last we're going to add a shadow you can see here we're kind of repeating ourselves so we've already added a shadow here and a corner radius a background etc so we can actually copy a lot of this stuff and add it into a modifier that we can reuse so let's just copy this and let's create a new file it's just going to be a swift file and let's call this modifiers [Music] these are pretty easy to make so all we have to do is create a struct and let's call this card modifier this just has to be f type v modifier inside of here we have a function [Music] that is going to give us some content and we have to return the view so we're just going to take this content and we're going to add our shadow to it and corner radius so once we have this what we can do is actually use it so instead of adding in our quarter radius and kind of repeating ourselves everywhere what we can do is say modifier and pass in our card [Music] modifier and it'd help if i spoke that correctly so i spelt this incorrectly there's actually an eye here and then now if we jump back here and add our modifier the last thing we need to do is just make this stretch so let's give it a frame [Music] and give it a max width let me use infinity i just want to add a height let's just match the height that we have here in figma so let's see is 163 because we're actually gonna have cards we actually let's use the width that we defined here in figma we don't want it to stretch i was thinking here that we were making our card again for some reason so let's give this a width of 99 just like that all right so now this is starting to look like a lot more like our design the next thing is how do we make it scroll so this is pretty unintuitive but we have to do a level of nesting so we have a scroll views with ui so let's wrap our content inside of that [Music] [Applause] and we have some funky behavior here so the next thing we need to do to tell us with ui that we want like a horizontal a scroll view is to wrap everything inside of an h stack so one more level of nesting i'm just going to highlight everything and indent it so now you should have scroll view h stack because we want to scroll horizontally then the second part of this is we need to repeat ourselves an x amount of times so we have a lot of these things enter views rather than copy and pasting everything we use for each [Music] for each needs some kind of data for now let's just create a range [Music] and nest everything again [Music] then we also have to provide this id parameter and we can just use the keypad map for self all right so after all said and done you should have something like this we can see that it's not really scrolling the way we want to so it's scrolling uh vertically so on scroll view we actually have a parameter where we can specify how we want it to scroll and all we have to just do is type horizontal you can see now this scrolls horizontally these are really skinny and let's just try modifying the frame see if we can achieve our desired size for the item all right so the last thing we want to do with the spacing is try to fix these gutters here so like the spacing between each of these items let's remove the padding from our v stack which is the cell and let's add it onto our h stack so we can add padding here and let's be a little bit more specific let's uh add padding to the top and to the bottom [Music] so that looks great the last thing we need to do is add some spacing between our items so what we can do is access the spacing here and just set it to 12. now we just need to style this text if we jump back to our designs [Music] we can see that it is heavy it's a font weight [Music] last we have our font down here and this is going to be medium [Music] and size 16. [Music] okay so now that our views start to match the designs we have a few things we need to solve so the first thing is we need some kind of data to display inside of here the second thing is yellow uh background should only be for the very first [Applause] card so the first thing is let's get some data in here and if we look at our api we can see that we have an array of hourly and that for the most part it looks kind of like our current struck they're pretty similar so what we need to do is just jump back to our hourly structure let's give an array already forecast [Music] so here we need to pass something in so inside of this initializer down here we need to pass in some data so let's access our weather service shared get the json and pass an hourly just like that so let's start using this data now um the interesting thing about it is we just pass it in here but we solve this problem of highlighting just the very first card so to solve this what we can do create an array and now just access our hourly forecast and we wanted that enumerated so what numerator does is it gives us i'm gonna close this real quick so numerator gives us the offset or the current index with addition to every single item so here instead of self let's use offset [Music] now similar to what we did with our extension that we created we have current plus extensions we kind of need to do the same exact thing but for hourly so here we can do say extension and just so we can see it side by side let's look at the data here just so we know what hourly is so we have a daytime similar to what we have in current and we need to access that and be able to format it similar to how we did it inside of this current formatted date all right so now what we can do is copy this formatted date and we're going to create it on hourly so for this format i just looked it up it's going to look something like this the next thing we need to do is again just format the temperature and this is pretty repetitive here and last but not least just like this we need the icon um you can see that it kind of gets a little repetitive here but it's because these models are really close to each other um it could be argued that we can combine them but again we generated this code so it's just code that we didn't write so there's nothing really we can do sometimes you repeat yourself a little bit but two times is music isn't that bad usually when you repeat yourself a third time that's when you kind of want to reevaluate things so let's take a look at this offset and we basically want to show now only when it's equal to zero so it's gonna look something like this otherwise let's show [Music] our forecast then we have formatted date next we just want to show the icon [Music] then the very last thing we want to do is show our formatted temperature [Music] [Applause] boom just like that we have it complete so i attacked on this modifier or i tacked on the am pm just so we can tell uh what time of day it really is without it it's a little confusing because you don't know like it's at nine o'clock at night isn't uh whatever i guess you can infer that but i think it kind of is easier when we add it on to the time the last thing we need to do is just uh change our background so it's coming back here to this modifier and what we're going to do is just do the same thing as we did for this text [Music] all right so this is already starting to look really good now all that's left is jump back to our content view and add this in and now that that's here it's starting to look a lot more complete see that we can scroll through this the one thing i want to do is add some spacing actually up here and we can just tack it on to the very outer v stack [Music] let's just do 16 for now all right so we can move on to our very last two views if we hop back to figma we can see this one's pretty simple we just have a button here with some text so in order to achieve this what we can do is create a button and for now we can just have an empty closure for the action and for the label all we have is some text and last we just have an image so you can see our button here is centered and we want it over to the right so all we need to do is come up to our v stack and specify an alignment [Music] and if we look at the designs the foreground color for both of these is going to be black [Music] all right so that view is pretty easy now we're on to our very last one this one's gonna be a little bit more difficult you can see that we have a list and inside of this list each cell has an icon the day we have a little description on the weather and we have the high or the low and high temperature for that day last but not least we have this label down here that says next seven days let's jump back to xcode then in our project navigator we can create a new view and this can be a swift ui view [Music] let's call this daily forecast view now let's start by creating our ui so the very top level it's created a fee stack inside of this v stack we have an image and for now we can just use cloud for placeholder and before we continue let's wrap everything inside of the each stack so every single cell was horizontally aligned or its content was horizontally aligned so next to the image we add some more [Music] text followed by a little description [Music] then we want to have some kind of space before we show the high and low text now we also have this little dot icon that's between our description and the day and in order to get that you need to click select option eight and it will create this little symbol here so this is the basic item that we have and now we kind of just need to style it a bit if we jump to our design we can start off with this text which is medium size 16. [Music] then we can add a font weight and i believe this is going to be the same for all these labels all right so that's starting to look a lot better what we can do two is add a modifier onto our v-stack and this is going to be our shadow modifier so this supplies the shadow to everything we can see too is we have a little padding here so let's add a padding to our h-stack and the last thing we can do is just give it a background all right so we managed to create one item but we need to kind of repeat ourselves four times and can't forget this label down here so first let's start off by how could we repeat ourselves and we've done this before we're gonna wrap everything inside of four each [Music] and we're gonna create a range up to four and we need to provide an id so once you're finished for each you should have something like this um what we want to do is eliminate this padding that we have between all these cells and i believe that it's just spacing that's implicitly added to our v stack so we can specify zero so that gets rid of of the spacing uh the last thing we need to do is just add some text [Music] and this is going to be outside of our h stacks or outside of our four each um in our v stack and all it said was next seven days and let's also add some padding so this is intended to be a button so what we can do is nest it inside of a button now when we do that we need to apply a foreground color [Music] and let's just add gray of course that cards starting to look a lot like our design i'd say the only thing that we'd want to add is maybe a little bit more padding so one thing with swift ui is you can actually add multiple modifiers that are the same so if we want double the padding what we can do is just specify padding for leading and trailing so this is starting to look pretty good uh the next thing we want to do is display some real data so right now we have things hard coded uh and we want to display the actual daily forecast so similar to what we did in our extensions file we're going to do the same for daily so this view is going to expect an array and if we look at our api.swift we can see that we have this array of daily so all we have to do is just consume it inside of our view [Music] and let's jump down to our initializer here we can use our weather service all right so now all we need to do is just format our data that way we can easily consume it inside of this view so if we jump to current plus extensions and if you wanted to split these up you can create an hourly plus extensions but for brevity's sake i'm just gonna have everything inside of here let's create another extension and this is gonna be on daily similar to everything we have here we kind of want to copy a lot of it so let's copy these three things so we have a formatted date and all we need to do is supply the modifier or the format here and that's just going to be three e's the last thing we need to do is figure out whether this date that we receive is today because if it's today we want to display that text what we can do is use the calendar api and use this function here which returns a bool telling us whether if our date is today so if it is we'll just return today otherwise we'll format it next thing we need to do is format this temp so we are displaying the high and low just so we can see this side by side we can flip to our api down swift and jump to daily's definition and you can see we have this temp object and here we have a mini to max so we just need to access that and because these are doubles let's wrap them inside of strings or inside ins that way we don't get any decimal places so icon names can be icon name the very last thing we need to do is provide a description and if we jump back to we don't see anything for a description but i believe if we go inside of weather inside of this truck we have a weather description [Music] so let's start off by clicking option eight and that gives us our little modifier here or our little symbol here that's gonna kind of separate this formatted date with the description then what we want to do now is just access the weather get the first object or the first item in an array i should say and we want to access the weather description now because this is optional what we can do is just provide a default one we can just say none or no description something like that all right so the last thing that's left to do is to hook this up all right so back the daily forecast for you what we can do here is use this closure argument and now all we need to do is access our data source so in this case it's going to be daily forecast for the index and this is going to be icon name and let's just do that for the rest of these [Applause] [Applause] all right so once you're done with that all you can do you can refresh canvas and you should see something like this so obviously uh it doesn't look like our designs um the first thing i notice is the format for the date is off so we need to fix that next thing is we should capitalize this description and the last thing is why is this temperature showing zero so let's jump back to our extensions and let's tackle the easy things first so here with our description we can capitalize this this format attempt you can see that we're actually dividing when we shouldn't be so let's add another bracket and here we just need to use string interpolation so no dividing this is just going to be a symbol that separates the min and max temperature so the last thing is this format so we need to provide some kind of format that matches our designs and similar to how i showed in the previous sections where we can actually figure out these formats on that website what we were missing is just one e so it should be four [Music] so let's jump back to our daily forecast view perfect so that's starting to look exactly like our designs so the last thing that's left to do is just to use this inside of our content view so right below this button everything's looking pretty nice um the one thing that i see is that some things are a little squished so if we take a look uh here let's just see what happens when we get rid of this spacing okay so this starts with better you can see that our title here is a little snug as well as this one here for more details so what we can do is just add padding to those two things [Music] alright so after removing the spacing and adding this padding starting to look a lot like our designs now let's just run this on the device all right so everything loaded on device we can see that we have the city still that's looking really good we can scroll through our hourly forecast we have our button here if we decide to show more details we have our daily forecast here we have a button here if we ever decide to do anything with it the last step obviously would be to hook this up to an api and if you like this style tutorial you definitely like that cause i'm gonna go into the details of creating an api client actually interacting with the api getting live data and we're gonna be messing around with the location so that you can fire this on your iphone and get the weather for your current location but i hope i gave you a good foundation on what it takes to build an app in swift ui and if you enjoyed this and go all the way this far be sure to drop a like on the video subscribe to the channel i have a few more tutorials planned before the end of the year so you definitely don't want to miss out on those all right folks see you in the next one bye
Info
Channel: Gary Tokman
Views: 3,730
Rating: undefined out of 5
Keywords: swiftui, swift, swiftui tutorial, swiftui 2.0, swiftui basics, swift ui, swiftui tutorials, swiftui course, swiftui 2, swiftui app, swiftui for beginners, swiftui mvvm, learn swiftui, apple swiftui, swift ui tutorial, what is swiftui, beginner swiftui, swift 5, swift app tutorial, swiftui navigation, swiftui background, how to learn swiftui, swift code tutorial, swiftui 2.0 tutorial, swiftui beginner, weather app swiftui, combine tutorial, url session combine
Id: -Q-Gc5t0zoI
Channel Id: undefined
Length: 111min 1sec (6661 seconds)
Published: Thu Dec 03 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.