TLDW logo

SwiftUI Fundamentals | FULL COURSE | Beginner Friendly

By Sean Allen

Summary

## Key takeaways - **SwiftUI core skill: moving data**: The foundation of building SwiftUI apps is passing data between views, not animations or UI - that's the mindset shift from UIKit's imperative to declarative paradigm. [00:47], [01:08] - **Refactor views for readability**: Extract subviews into separate structs to make ContentView readable - balance line count with clarity over minimalism. [01:02:18], [01:03:14] - **Modifier order creates view layers**: Each modifier wraps the previous view in a new view, so order matters - frame after background won't fill the frame. [21:07], [22:10] - **MVVM separates display logic**: ViewModels handle logic between Model data and dumb Views that just display - only needed for dynamic screens. [02:47:00], [02:51:16] - **UIViewRepresentable bridges UIKit**: Use UIViewRepresentable + Coordinator to pass data from UIKit (camera) to SwiftUI via delegates - coordinator relays between paradigms. [04:05:24], [04:26:49] - **@State persists across view recreation**: Struct views get destroyed/recreated constantly, but @State property wrapper stores data separately to maintain UI state. [01:12:32], [01:13:12]

Topics Covered

  • Full Video

Full Transcript

welcome to Swift UI fundamentals in this video I'm going to talk about you know what we're going to learn in this course and how we're going to learn it and kind of the overall flow first up this was designed for people who at least have the basics of Swift down you don't have to be a swift Pro

but but at least know the basics and if you don't know the basics check out iOS Dev Launchpad we go over all that so this course is meant to build your foundation in Swift UI and focus on what I believe is the core skill and that is moving data around you know Swift UI is declarative which is quite different from the imperative programming Paradigm we all may be used to with UI kit right

it kind of flips it on its head you have to completely think about things differently right so it's a mindset shift and that mindset shift and properly passing data between views like that's what I want to focus on in this course like yes Swift UI can do a lot of awesome animations crazy cool UI stuff but again I want to focus on the foundation of building apps and to me that is

passing the data and getting your app to act how you want it to right right I say that all the time when I first learned Swifty why getting my app to look like I wanted to right with just building the UI to me that was like the easy part where I ran into frustrations and headaches was passing

data and getting my app to act how I wanted so that's what I want to be the focus of this app fun cool UI and animations that can and will come later alright so how is this course going to work let's talk about the flow overall we're going to build four apps it's going to start off pretty easy but we're going to progressively get more difficult and build over time to where the final

app is a bit complex you know for a foundational course and I'm going to introduce Concepts slowly at first and we'll get a lot of practice you know building with them using them because as you know I'm a big believer in like practice repetition you don't just read one article or watch one video on a topic and then you know it you gotta practice practice but we do start off pretty easy so if

you do have a little bit of Swift UI experience and after the first two apps you're like oh man this is super basic just just wait just wait but uh okay let's let's talk about those apps so the first one is just the UI of a weather app this is the introduction to the course so we start off super basic I want to get you familiar with the foundational tools and just building UI in

Swift UI after that introductory app I go into more of an explainer session some talking head you know graphical videos where I explain you know imperative versus declarative and the differences I I talk about how swift UI updates its views in the view tree hierarchy talk about view modifiers view Builders right we kind of dive into the Core Concepts of explaining but then we get back to

code in the next app it's about Apple Frameworks where as you can see there's a grid you can tap on a framework learn more about the framework so not only will you learn how to build this kind of app but hopefully you'll get inspired by reading about these Frameworks in and maybe get your next big app idea but in that app as you can see we're adding a couple screens we're starting to dip our

toes into passing data from screen to screen like I said we ease into it and get progressively more difficult now the third app all about the bar code scanner this really focuses on UI kit integration with swift UI right because you know Swift UI is pretty new a lot of stuff still isn't built in such as the camera like we see in this app and this app focuses on passing data from UI kit

to Swift UI when you have to integrate UI kit that's using UI view controller representable in coordinators to pass all the data so the whole point of this app is to get you used to using that because if you're building apps in Swift UI it's very likely that you're going to have to go to UI kit for some things and finally we finish off with a more complex app well we'll complex for a

foundational course where you can order appetizers you know see a detailed view of it add it to your card or your order and then place your order to be clear I don't want to have any misconceptions we're not implementing like stripe and actual Payment Processing that's a that's a bit outside the scope of this course but I don't want there to be any like wrong expectations now this app

you know besides what you see we're going to deal with network calls in this app so we're going to do proper error handling oh alerts you know some Advanced animations so again this is where it gets a little more complex you know above what we did in the previous apps and during each of these apps we're going to be refactoring along the way we're going to be talking about project organization and

I'll be providing various levels of challenges after each app if you do want to push yourself further and further to build upon the base you know of what these apps give you after we build the four apps we're going to have a review section and I think this is going to be a very valuable section because it's part of the learning process right you're going to hear me talk about it we're

going to get a chance to build and play with it a couple times right but once you've seen it in action you've actually touched it and then now if you go back and review it I feel like that's going to really solidify your knowledge and just really drive it into your head and then lastly my final disclaimer the only thing I can promise you is that Swift UI is going to change right so

don't treat this course as like the final end-all be-all of your Swift Foundation right I want to give you those foundational skills so that you can easily grow and evolve and adapt as this world of Swift UI changes and evolves itself so just keep that in mind things are probably going to change but hopefully you leave this course with a solid foundation so you can change with it

this course has been updated for iOS 15 and iOS 16. this course is structured into four apps and I did the updates at the end of each app for example the first app you'll do is the weather app so at the end of the weather app there's an what's new in iOS 15 and then there's a what's

new in iOS 16. and then the same thing for each app after that I put the updates at the end of the app so you can still see the old way because a lot of apps have to support older versions of iOS iOS 14 iOS 15. so if I just redid everything for only iOS 16 and above well you're missing out on

how to do things the old way which you may need I also think it's good for you to see the evolution of how things change and how we go about updating projects you know as new iOS versions come out so if you're going through this course for the very first time and before you get to those iOS 15 and iOS 16 sections you see some deprecations or xcode Warnings don't worry wait till you get

through the updated for iOS 16 version we will address those you'll also see some what's new in xcode videos I believe xcode 13 and XO 14 and that's because xcode itself is changing evolving over time so again if you're going through the first time you see something weird or different in xcode make sure you check out those what's new in xcode videos to help you out

over the next few videos I'm going to introduce you to Swift UI by building this weather app well at least the UI for the weather app now as I said in the course overview if you remember the purpose of this app is to not give you the full deep explanations all right away the purpose of building this app is to show you Swift UI in action give you a light introduction to it so as

I'm going through this app if you're not quite following everything or I'm moving too quickly that is by Design because again I want you to see it because when I give deeper explanations in future videos I think that will make it easier for you to understand what I'm talking about right if I just Dove right into those deep explanations right away and you hadn't seen it in action it's

going to be like confusing but if you've seen it in action then I give the Deep explanation I think you'll be able to connect those two and actually understand what's going on not to mention this is going to be the first of a couple apps we build in the course and we're going to be doing all this a lot you're going to get plenty of practice and repetition so again like I said in the intro the

flow of this course over those apps is the first that may be confusing the second app you're going to start to get it by the third and fourth app hopefully you're typing this stuff out before I even say it that's the goal that's what I want out of this course so that's my disclaimer and again try to refrain from asking like specific questions on these videos in the comments because

I'm very likely going to answer those in the videos after we build this weather up again the whole point of this is just for you to see it in action all right let's start building so open up xcode create a new xcode project and I'll make this full screen here no Siri not you okay so right away you see uh you have a couple options when building a swift UI app like just an app

um well you can also click multi-platform but here's the thing in the early xcode 12 betas when you clicked on multi-platform which would give you Mac OS iOS iPad OS that stuff um you used to be able to create an app here well in the release of xcode 12 it's gone and allegedly it's back in the xcode 12.2 beta so if you're doing this later you might see it in xcode 12.2 and Beyond but but

you should be able to create a multi-platform app that's one of the features of Swift UI so for now because I am on xcode 12.1 just click app for iOS and hit next and I'm going to name this Swift UI Dash weather that's you can name it whatever you want that's what I'm going to name it and make sure you have Swift UI as the interface checked and the life cycle Swift UI app don't worry about

core data or test we're not there yet I'll go and hit next and save it wherever you like I'm gonna put it on my desktop for now and here we are this is what a swift UI xcode interface looks like now your preview may not be up and running like mine isn't so hit resume and this is kind of what is

uh nice about Swift UI is you get you know this hot reloading now in theory that's what you're supposed to get oftentimes the preview acts kind of finicky sometimes it's slow as you're seeing this is on an iMac Pro still a little slow so to be quite honest when I'm actually building my apps in Swift UI I'm like rarely using the preview and only for very specific like screens

but again Swift UI is so new I expect previews to improve a lot over the coming years first of all we don't want an iPad Touch 7th generation let's go to the iPhone 12 Pro the new hotness okay here we are and I'm gonna you can adjust the size here now what I'm going to show you here is how you can

visually edit code but I'm only showing this to you out of what I feel is kind of an obligation to at least let you know it exists because I never use it I recommend you don't use it because once you learn how to just like write the code it's 10 times faster you can be so much more productive

but I want to show you this exists and maybe it'll help you when you're first learning but I I don't recommend getting used to doing this and making this like the way you do things but before I dive into that let's actually break down what's going on over here in our content view so Swift UI is all about views I'll dive more into that later but every view you create is going to return a body

and it's going to return a view so right now our content view has a property called body and it's returning text hello world and that's what you see here so that's what's going on right now and of course we're going to build a lot more code in there to to expand on that but let me get back to

this preview real quick just to show you this so I can get it out of the way so if you do command shift L you can kind of pull up your modifiers now more on modifiers later but it's kind of how you customize a view again we're going to do a deep dive into modifiers with its own dedicated

video so right now just know this is how you kind of customize a view or drag a view on there so let's say we want a button below our hello world text over here well if you're using the preview you can just literally drag that button and you can see where you put it you can put it below it

above it to the left of it to the right of it now this is where Stacks come in and stacks are very fundamental to Swift UI we're going to be using them so much they're going to be second nature by the time we may even be done with this first video but definitely by the time we're done with the course Stacks are going to be second nature to you so if you're a little confused now don't

worry but you can see the little message at the bottom adding a button to the new horizontal stack along with existing text and if I move it to the bottom it says adding a button to a vertical stack along with existing text so let's add it to the bottom and create a vertical stack or a v-stack so now what you see happen is the button is in this vertical stack which is that red outline

that's the frame of it so you got the hello world text and a button now the cool thing kind of cool right you dropped it on your preview and look what happened in the code the code automatically popped in it popped up a v-stack with here's our text that we had and then I put a button Below in

the v-stack so that is pretty cool I'm not going to lie when you see just drag and dropping and it makes the code for you you're going to think wow that's an awesome way to do it that's great it's great for like little small stuff it's cool yeah trust me you're gonna be just wanting to write code more often than not all right let's do this one more time command shift L to pull up

your library and let's drop another text into this except now we're not going to uh drop it so I could drop it here to just add it into the v-stack that we have the vertical stack but let's try something different let's put it to the left to create a new uh horizontal stack in h-stack right so I drop it there boom see placeholder for the text and then so here's the horizontal stack

right you got the placeholder on the left and then our v stack so you can like Nest your Stacks as you're seeing so the v-stack of hello world and button is now on the right of the H DAC and you can see this here right the whole thing is wrapped in this H stack and then to the left of the H

stack is the text and then we have our v stack here to the right so again you can see you can nest hdax and V Stacks now that's all I'm going to show you for the drag and drop again because I don't want to I don't recommend using that but I felt like I needed to show that off now let's

take a look at the design and I'm going to break down the hdax the V stacks and the Z stack haven't talked about that yet of this design to hopefully you know make you start understanding how these Stacks work because again this is like fundamental to Swift UI you're going to be writing a million Stacks throughout your career so looking at the design the elements on the screen that are on top

of the background color is one big v stack right so as you can see in this outline the the city name Cupertino uh the icons everything is within a v-stack but like I mentioned you can Nest other Stacks in that for example the weather icon that we have the cloud and the Sun and the 76 degrees like that in and of itself is its own v-stack nested within the overall v-stack and down here

you can see we have individual v-stacks right of the the day of the week like Tuesday the weather icon and the temperature that in and of itself is a v-stack but it's nested within the overall H stack that is the days of the week going across and again that itself is nested within the overall v stack and then of course we have the button at the bottom of the v stack there so hopefully that

gives you an example of you know how these Stacks works the HD attacks and V stacks and again we're going to build this so you're going to get more in-depth knowledge but that's it on the surface and then the Z stack that I haven't talked about is that is kind of like vertical layers right so for example the v stack that holds all the elements is on top of our background view which

is the color gradient right so that is the Z stack and that's kind of like vertical uh view hierarchy if you will so that covers the three main types of stacks again we're going to build this so you're going to get more knowledge and we're going to build a bunch more apps with them so let's get to it all right so back what we were messing with before one thing you can do when you're not using

the the drag and drop preview is get rid of this pane on the right that'll give you more room I like to make my my canvas a little smaller if you want the mini map cool I tend to not not I think the mini map super cool I just never use it so I click it off because again I like screen real

estate but let me show you something real quick and this is why I prefer the code way like I can go from an H stack to a v-stack like in a second just by going deleting H to V and now you can see uh it changed so again I find code so much so much quicker and again this v-stack let's change it to

an H deck literally by changing one letter in your code it changes the layout of your screen so that is the power of like doing it via code so one little one little tip there that's why I like that so on that note uh we're gonna have a remember I said the whole thing is a z stack so

I'm going to make that a z-stack and you can see it put everything on top of each other not what we want so let's delete all of this here because the first thing we're going to build in our Z stack is our background and if you look at the design again look at the background it's a nice gradient

uh color for the background so the first thing we want to do is actually make a color now a color is a view like everything in Swift UI is a view again I'll be saying that all throughout the course so let's do color dot blue right bam okay so you see in the color it fills the entire space available

which is everything but the safe area but you notice on our designs like we we don't we don't want to respect the safe area for a background we want to fill the whole view how we can fix that is by adding a modifier onto our color to say dot edges ignoring safe area all as you can see in our preview that fills up the whole phone and we put that on our color view because that's

the view we want to ignore the safe area when we actually put our content in there we want to respect the safe area for that but our background ignore the safe area now that demonstrates color how it fills everything up however our designs call for a gradient not not just a solid color for that we can create a linear gradient so as you type linear gradient there you go let's get

our initializer here you can see it takes in a a gradient a start point and an endpoint so for well there it gives us default values there so you can start to see how quickly that comes in so for our gradient here we want an array of colors so let's do um we want dot blue and then dot white right

because this is kind of like like the blue sky uh thing that we're looking for not blue blue white all right so you see blue white now starting point is leading and trailing so you can see the gradient starts in the leading which is on the left here and it goes to the right however we want uh Dot and you can just hit dot to see all your options here we want top leading because we kind

of want it to come down from the right right and then dot bottom trailing is what we want we want kind of want that angle there right so there you go so it starts starts in the top left goes down to the bottom right and we get kind of that that like blue sky uh look now gradients are

nice and flexible right if you wanted to get kind of crazy with it right we have an array of colors here you can add as many colors to this array that you want and again I don't want to get too wrapped up in like every detail about the UI but I thought this was pretty cool to share so I can

dot Blue Dot Red Dot white I guess that's pretty patriotic didn't even mean to do that but you know let's add a set of green in there right just to really drive the point home here green comma not semicolon comma damn Mike's in the way so you can see you can get kind of crazy with the gradients just by adding colors to the array set getting a start Point setting an endpoint and Swift UI does

the rest so that's just one little taste of like kind of the powerful stuffs with you I can do and there's so much of that and I did dabble in it here but remember the point of this course is to really focus on like the passing of the data and understanding how swift UI works you can do like

seven courses on all the cool UI stuff you can do but that's not the focus of this one so that's as far as we're gonna go on like playing around with with cool stuff at least at least right away so we just want the blue and the white for our gradient and we're actually going to create a custom color for light blue because the white is like too much but that's going to come

later and quick note you'll notice in Swift UI a lot of times has very long like initializers so a style that I've adopted and many people already did this but a style that I've adopted on the long ones is to start basically you know lining up my my parameters vertically like that um for for My Views and you'll see me do that throughout the course and it really depends

on how long you know the initializer is so as you can see our background gradient is set up in our z-stack so then next thing we need to do is start building that overall v stack on top of our background linear gradient and we're going to do that in the next video we left off last video getting our background gradient all set up well now we're going to start the process of building

the rest of the UI elements to eventually get to the final product that you see there and we're just going to go top to bottom so first let's start with the city name that we want to put in there okay so back to our code as a recap we have our Z stack with a linear gradient now remember

Z stack is kind of like vertical uh you know view hierarchy layers if you will remember we said all the UI elements are held within one v stack back when I went over that last video so here this is where now we're going to start typing the code not dragging and dropping go and start typing the stack and get the autocomplete here open and close bracers there we go there's our v-stack you

don't see it yet because nothing's in there now we want the city name right so that is a text text is a view that takes in a string so we want to do Cupertino California to Apple's headquarters now you'll notice it is dead center of the screen no styling that's not where we want it that's not what we want it to look like so first up let's get it looking how we want right

and that can comes with modifiers again more modifiers later but one thing to note about modifiers as you're adding multiples now you may be used to UI kit where you would say you know uiview dot background color equals red you're telling that view to make its background color red Swift UI is a little different in that every modifier wraps the previous View in another view I

know that sounds confusing again we're gonna we're gonna dive into that later so just remember that modifiers are a whole other view wrapping the existing view so when I do uh font and I do dot system here we go we're going to get size we'll do 32 font weight medium and design is a default so that just wrapped the text view in another view you know with the font and the system stuff same

thing when I do foreground color right we're going to make it white dot foreground color dot White all right there you go now you're seeing it update so again it's getting wrapped in another view and the reason that is important and you'll you'll understand that the more you get practice as we go through the course is the order of the modifier matters now if I do dot background color

and do color dot red you can see the background is red now watch okay so that is a view now I'm going to wrap that view in a frame all right so let's dot frame because you can like Define the frame and we'll just do like a a 200 by 200 frame so now you see on my preview here you can see the red outline that represents my frame that's just because I have this line highlighted

by the way like that red outline is not going to be there let me highlight the the text view or let me highlight the linear gradient right so you can see that's what that red outline means on the preview whatever you have selected it's going to show you kind of the the details of it so by clicking on the text you can see I have a 200 by 200 frame however my background color didn't

fill the frame because I put the frame on after I did the background color right we wrapped it in a frame but it already had its background color so that was a very simple example but the main thing to take away here and again we're going to get plenty of practice with this is that the order of your modifiers matter because your modifiers are basically wrapping the existing view in another

you and the reason Swift UI can do that is because views are so cheap and Swift UI they get destroyed and recreated all the time more on that and more more detail right I don't want to get too into the weeds right now but I wanted to point out the order of modifiers matter and what modifiers are really doing okay so let's delete that example here and now we have our our text

looking like we want it to right that Cupertino you know California it's not in the location we want and let's talk about why because a v-stack right is only going to take up as much space as it needs if I click on the v-stack to highlight it in red on my preview look how big my v-stack is only as large as the text is right so if you want that v-stack to stretch there's a view called

a spacer right so if I put a spacer below the text it's going to push it all the way to the top so what that means is basically the v-stack now is the whole length of the screen essentially however the text is only taking up that top part and the rest of the space below the text is the

spacer so strategically using space to move your UI around is often how you lay out your UI and you can get real custom with it you can set a custom height or width on the spacer more on that later just know that spacers will kind of like fill the entire space so that's kind of what we want however Cupertino California is hugging the notch a little bit too much so another modifier we can

put on text is padding so I can do dot padding one this is kind of like a default thing all the way around and now you can see my red outline on the text has some padding in it right it's not it's not hugging the Cupertino California text so tightly because it has padding around it so now with that padding our our city name is spaced how we want it right it's not hugging the notch

too much and again you can do padding uh 100 okay now look at the padding I added that's not what we want of course but I want to point out that the padding is is flexible you can do padding dot only on the bottom space you know 200 right and you'll see now there's only padding on the bottom

so padding is is pretty flexible now one thing I want to show you before we end this video is one thing you'll notice when working with swift UI is that the list of parameters is often very flexible like you just saw that I was able to do top you know dot bottom.top with the comma like it almost looked like I was making up my own parameters well let me show you why that is if you command

click on padding go to jump to definition sure I'm trying to get through the documentation here okay so here we are here's the padding implementation right well what Swift UI does a lot not not all the time but you'll see this a lot is it sets default values first parameters so you can see the edges set is equal to all and the length is equal to nil so when they give default values what that

means is if you don't include that parameter it's going to default to the default value of course so you'll see that a lot in Swifty why where the you know parameters are often very very flexible and I know that confused me at first I was like wait a minute like I can pretty much write whatever I

want in the parameter how do I know what I can and what I can't and then when you dig into the documentation here basically it reveals wise because they set default values for a lot of things so it's very flexible which I like all right back to our code here so like I said the spacer is filling up uh sometimes you have to hit resume as you see this previews can be finicky

sometimes so if you see that resume button make sure you hit it so your previews are up to date um so now like I said the spacer is filling up the whole Space obviously we're going to add more elements in here with a v-stack if you go back to the design now we're going to add our Cloud Sun icon or whatever weather you want to pick put that icon there and the temperature and

that's going to be its own v-stack but in order for me to get that nice looking icon like that is an SF symbol so I want to introduce you to SF symbols show you how to download that and get you started using that because we're going to use that in a lot of the apps the rest of the course

all right SF symbols well this is SF symbols 2 at the moment maybe it's three by the time you're taking this who knows anyway SF symbols were introduced in 2019 kind of when Swift UI came out and as you can see here it's just a bunch of built-in uh iconography that Apple provides and they are awesome if you haven't used them yet I think you're going to learn to love them we're

going to use them throughout the course but with the flexibility here so this is like the official developer site this is the human interface guideline site I'll link to both of these in the description but to be honest if you just Google SF symbols these are the top two results or click the link whatever you want to do so here's the human interface guidelines on SF symbols so

you can see they're nice multi-colored there's 2400 of them uh they're great they're built into xcode free to use if you've ever struggled to find icons for your app you know the struggle that's why these are awesome another cool thing is like they have like font weights attached to them they adapt to Dynamic type they're just great and by font weights you can see here right an ultra

light version of the icon all the way to like a heavy bold version and everything in in between so they're very flexible support Dynamic type they're they're awesome I'm so happy Apple you know started doing this and again it's only year two in existence and they're already at 2400. I

just imagine that they're going to get better and better and better over time for example new in 2020 uh they announced uh colored icons before it was just monochrome just one color you could change like the tint color didn't have to be black or white you can make it any color but it was all monochrome well now there's like multi-colored uh icons so that's great um so

let me show you how to download it again back to this one the Apple developer website not the human interface guidelines if you scroll down a little bit make sure you don't download SF symbols too not SF symbols 1.1 because SS symbols 2 has you know 750 new symbols and it got the multi-colored symbols which we're going to use for our Cloud right remember the cloud was white the sun was

yellow that's an example of a multi-colored SF symbol that we're going to use so once you got that downloaded and you open it up and I made it full screen again here's all 2400 icons right and you see the categories on the left but we'll tap on gaming just an example she got all these controller icons d-pads buttons Transportation all kind of cars planes cool so any topic you

want over here uh click on multi-color you can click there or you can click this little color wheel to get the multi-color now you're going to see most of mine are red this is because that is my Mac accessory color if you haven't I get asked this all the time but my xcode how I made it red if you go into General quick little tip here general settings highlight color red accent

color red you can pick any color you want watch when I change this to Green look now all my icons are green so that means whatever system uh color that the user has that's what's going to show on these multi-colored icons at least the ones that have that um so anyway now you can start to see our weather ones that we're going to use here's the cloud in the Sun but again play around in SF

symbols scroll you can see there's a ton of cool ones literally 2400 of them so I how to use SF symbols we'll get into in the next video I'm going to show you actually how basically you just copy and paste this name right here like Doc fill badge dot plus and there is a way to copy paste we'll

talk about that um but I wanted to use this video to introduce you to SF symbols show you how to download it and definitely download it don't just watch this video because we're going to be using this uh all throughout the course so get this downloaded and let's move on to the next video now that we got SF symbols downloaded we're back in our project uh pulling up the design again what

we're going to create right now is our v-stack with our main weather icon and the temperature we're going to focus on that for this video so looking back at our code right we have our overall z-stack and then we have our overall v stack which again holds all our elements right now all we have is our text that you see at the top there and our spacer which fills that up so we are going

to keep the spacer at the bottom and add another v-stack because the v-stack is going to hold again our SF symbol and our temperature text so an SS symbol is an image so if we Type image and then here's the thing like image has a couple different initializers if you do image name this would be like just an image in your bundle like you would have in your UI kit right where you do UI image

named the string right that's the same thing here however if we type system name this gives us our SF symbols right so now I need a string well what string do I need that's what we need to open up SF symbols to find out so I'm going to tab over to SF symbol and here we are I'm in my multi-colored section again now we're down to the weather again this cloud.sun.fill is what we want

so you can either type in that string or if you tap on it and do a command shift C so just like command C to copy but add a shift in there command shift C to copy that will copy the string and if we command tab back to xcode and do a command V to paste that in there you go Cloud Sun fill

there it is on the right exactly how we want it no it's not so all right so we didn't get multi-color uh we just got this very small you know black icon that's not what we want okay so first let's handle getting the multi-colored so what you need to do there you need to do rendering mode and then pass in dot original that'll give us the multi-color there you go it's still super

small as you can barely see probably um but at least we got the color combo we're looking for now images when you when you bring them into Swift UI you'll notice like if you bring in like an actual image like from your phone or something like that it'll blow up to like its actual size so pretty much all the time you're going to want to make your images resizable put that modifier

so now when you do that bam now it's huge because it's filling up all that space uh we don't want that either so we want to put a frame around our image to give it like a fixed size so again down here let's add another modifier to our image dot frame width and height so let's do 180 by 180 and

I get asked this all the time when I kind of do tutorials like oh where'd you come up with those numbers and I'm not doing it uh on the video but the honest answer is like I I guess the number okay that's too big and I just slowly tweak it over time to dial it in so you're going to see

that a lot throughout the course right just throw out these numbers just know that it took a lot of trial and error to like dial it into that number um which is nice and Swift UI because look I can say hey 180 or 180 or you know 80 by 80 and real quick instantly I can like get a feel for it so

again just trial by error so if you don't know these numbers off the top of your head neither did I I just figured it out okay so there's our frame it doesn't quite look right our cloud and sun is more of a landscape Type image right it's not as perfectly Square aspect ratio and it kind of looks like it's stretching a little bit to fix our square but we don't want to like

adjust our frame we want our 180 by 180 because if we go back to SF symbols a lot of these other symbols are a square so we want to keep our a frame a square we just want to keep the aspect ratio of the image so there's a modifier we'll put it below resizable dot aspect ratio content mode

and we can dot fit there you go so that keeps the aspect ratio but fits it within our 180 by 180 frame and now you can see that doesn't look like a stretched out image anymore that's that's the image we want so now that we have that we need to add our text again let's stay in the v

stack right and our little nested v stack here so now we want uh text of again a string to say 76 and if you do option shift 8 that'll give you the degree symbol I had to look that up I didn't know that either so as you can see in the text same thing that happened with our image it's the black

color it's small you know it's not exactly how we want it so again let's start adding our modifiers so add our font here now one thing about the way I'm adding font and we're not going to get into this at the moment so I do dot system so when I do system uh size and weight that is giving me the San Francisco font which is like the default Apple font and the other thing is this won't

support Dynamic type we're basically hard coding the font size and one Dynamic type is way too much to get into for this initial app but two our copper our city label and our degrees here we want to be really big like they're already big so they don't really need to support Dynamic type because they're already huge so we want to make this size 70 right told you it was huge and then dot medium

font weight and you can play around with this if you want it super bold if you want it ultra thin you know make your own play around we can delete that uh because again that's one of those default value parameters that I talked about with padding so again we have our uh 76 degrees looking how we want it we just don't have the color so again dot foreground color dot white there we go okay

so we're starting to see this come together a little bit now one final touch I want to put on this uh v-stat back that has our icon and our our temperature in it is you notice there's a lot of space in between there so there's a couple ways we can do this right we could add a spacer here with a very small frame in between uh you know maybe we could add some padding with a negative

number that's a little hacky uh however V Stacks also have parameters so do hdax and all that stuff um so if I do the initializer here you can see I have alignment spacing and content so you can align everything to the left line everything to the right uh or you know as an example and then we can set a spacing so we're gonna use a spacing parameter here and again because we

can we can pick and choose parameters because they're all default values on the other ones so spacing let's make an eight again I just kind of dialed this in and you saw the 76 get pushed up a little bit closer uh to the cloud and that looks about right and the reason it's not even a little closer is because remember the cloud in the sun is kind of like a landscape right we had to make it

aspect fit so our frame of our image if you look is actually more right so when we put a square image in there it's actually going to fill it up so something to keep in mind is some images may not all have the right aspect ratio so for example and I just have this memorized to be honest with

you I can do Sun Dot uh Max dot fill that'll give me the big sun and it's always good to like test your UI with multiple images if they're Dynamic like these so now we can see when it's like full bright Sun maybe it's a little cramped maybe I want to add spacing to 10 on my v stack there

to bump it out a little bit you can dial this in let's go back to cloud.sun.fill uh and there you go so again something to think about uh with SF symbols is they may not all have the same aspect ratio when you use them okay now before I move on to the next video I want to point something out right here's our overall z-stack uh you can see that we're adding all these elements right the

text the the image here it's it's starting to grow a little bit and you can imagine as we add our H stack with all the other v-stack views right that you see on the design here we add our button this could get a bit unruly now in later videos of this weather app I'm going to go back and refactor and

show you another cool thing about Swift UI is how you can really structure your code and make your view very readable right because you can imagine if this was much longer it'd be kind of hard to read there's a lot going on we're going to fix that in a future video but I want to lay out all the UI first so you can see what it's like when it's all laid out and then we're going to

refactor it all right on to the next one in this video we're going to build this h-stack of day views whatever you want to call it that has each individual day with the different weather icons but we're going to start this video with your very first challenge I know it's a little early we're just getting started but it's very similar to what we just did so the challenge here and just pause

the video real quick is to create this v-stack that has the the day of the week at the top uh you know the icon in the middle and then the temperature at the bottom and like I said just pause the video real quick because I'm going to get right into actually building it together you can check your answer then or if you don't want to do the challenge just we'll go ahead but I'm going

to be issuing challenges like this all throughout the course and at the end of each app I'm going to give you a kind of a list of things that you could do to potentially you know take this app further if you want to continue your learning and continue challenging yourself this is your last chance to pause I'm moving on three two one all right let's go so like I said we're building this uh H stack

of all these individual days so again back to our structure of our screen right we have the Z stack with the background of the color on top of that color background we have our overall v stack that holds you know all of our items within that we have our city text and then we have our v-stack that is our icon and temperature so now we want to add an H stack down here for these

days so again H stack okay cool but now remember within uh that H stack we're going to have five individual V Stacks so let's create our first one and you'll see we'll just end up copying and pasting a lot before we refactor we're going to refactor this but we'll just do our v-stack here and uh again remember it's it's a text at the top because it's our days of the week so let's just

kind of build out the rudimentary version here uh first so we'll say Tuesday and then below that is our image right because this is our so simple same thing uh that we have up here except you know let's just copy and paste this you'll see this happen a lot in Swift UI actually so we'll copy and paste that and now our frame isn't going to be 180 by 180 right that's huge in fact our frame

is going to be 40 by 40 here now you may already be seeing how we could potentially reuse these views right because it was the same thing as this image up here however the frame is just different so you can imagine we could refactor this into its own View and just pass in our frame size and then we could reuse it and resize it however we like you know we may do that later but that's

something you may see as this code gets repetitive same thing here with our text of the temperature again we're just going to copy and paste that down here the difference here is our font font is not going to be 70. here it's going to be uh 28 so there you go so you can see it kind of starting to come together however you know we copied and pasted the image in the text because we'd already

built that we hadn't built our day of the week yet so we're gonna have to format this ourselves so let's do that here we have our font again we'll do that system size 16 and like I said I'm kind of hard coding dot medium our fonts right now if you want to support Dynamic type uh you know you're not going to be whoops hard coding this and we'll give it the uh dot foreground

color of dot white and again back to kind of this idea of refactoring you can see a lot of the text we use it has the same font weight the same foreground color the same font the only difference is a size of 16. so you can see how you can make a custom text view that takes in a parameter of just

the size and now you have this white medium you know font size text that you can use all throughout your app where you just pass in a font size all right so we have our our v stack here built which is the start of our hdac that's just one now what I could do is literally do that copy and paste this five times but because our file is already getting long and to be quite honest

my font's got to be big so it's really hard to navigate around we're actually going to refactor to this part right now we'll refactor the rest of the file in a later video but in order to not copy and paste this chunk five times let's let's do that now so one cool thing you can do here is

if you command click on the v stack you can do you see you get a bunch of different options right and embed and all this stuff here let's focus on the extract sub view so it kind of helps you refactor Vector so we're going to hit extract sub View and now you see I get a struct down here below

the content view so this is his own Standalone thing if we wanted to we could put this in its own file separate we're not going to do that right now but we could if we wanted to and it gives it the name extracted view because it doesn't know what we want to name it so let's call this weather day view now let's look here remember pretty much everything in Swift is a view so whether debut has

a variable called body and it returns a view like kind of drill that into your brain we're going to be talking about that a lot now to make this reusable we have to pass in a couple variables so let's just look at this weather day view by itself and see what we need okay well the day of the week needs to be passed in right that's it's not always going to be Tuesday so let's create that

variable here VAR day of week and that's going to be a string so now that we have that we can replace Tuesday with day of week and then we're going to need the system name because not every day is going to be cloudy sunny right maybe it's rainy maybe it's windy so we're gonna have to pass in the image name so VAR image name call that a string or it is a string not call it a

string and instead of that we'll pass in image name and you're going to see how we use this how we're gonna have to pass in this information and then we're also going to need the temperature and that is also a string but actually you know what we're gonna even though we're not gonna use it like this in um in this app fully let's actually make this uh an INT

and then that way because like if we were getting this back from an API I don't know maybe it comes back as a string but most you know it's probably going to be an INT if you have like temperature using somewhere in your database so here we can do the instead of 76 degrees we can do string interpolation based on temperature that we pass in right we're going to pass in an integer but

we're going to convert it to a string here so now we have our reusable weather day view so now when I create a weather day view I have to pass in day of the week I have to pass an image name and I have to pass in temperature so let's go ahead and make five weather day views up here

on extracted view so we'll do weather day view it's going to take in as you can see and get that autocomplete back day of week image name and temperature so again day of week uh we'll start off with two Tuesday for this one uh image string for now let's just do the same that we have up here the cloud Sun fill we'll go back and like make this some variety with temperatures but

we're just kind of testing this and getting our you know the structure of our view in place and like I said sometimes the parameters can get long uh like to put return there now if your parameters are getting like four five six seven things you can refactor that parameter it takes or all the properties it takes in into its own you know object that you can create elsewhere and just

pass in the one object so there's a little bit of a balancing act here usually three or four parameters I start to feel weird about anything over four I definitely want to refactor that so I'm not passing in like 10 different things that's just personal code style preference you don't necessarily have to do that so again let's say the temperature is 74 that we pass in

so let's hit resume up here again sometimes your preview will stop and you can see on our v-stack here we have Tuesday and 74 degrees with the same Cloud Sun fill that we did so now let's copy and paste this five times and again if we had like a data model that had our days in an array we

could actually do this hdac you know by passing in an array that would parse out all that data we don't have that currently so we're going to kind of do it the the long way here so again here's our hdac with our five weather day views now like I said we just got the initial structure but it's not quite right it feels cramped up against uh the 76 degrees so in between our v stack

here which is our main kind of image that you see here we can put a spacer to push that down and remember spacer is going to push it all the way to the bottom so we're going to do something here right so we'll pushed it down it didn't push it all the way down to the bottom because I forgot

we have another spacer down here right so you can see the spacer is filling up the bottom and the spacer here is above that horizontal H stack right so you can see it kind of puts it in the middle so that's the power of spacers kind of like evening things out um the other thing here is you kind of notice they're kind of cramped together maybe so just like v-stack had the spacer or spacing

um parameter here so does an H deck I don't know let's just play around again this is how I come up with these numbers let's try 10. there you go spread it out to 10. man that's a little strike 20. oh not 200. let's see 200 is a bit much okay 20 looks about right all right so we're getting

20. oh not 200. let's see 200 is a bit much okay 20 looks about right all right so we're getting there it's not quite perfect but you can start to see it take shape before we mess with it too much let's let's kind of get our individual data in there so let's keep Tuesday the same because right Monday and Tuesday are probably going to be similar let's start changing our days

of the week so Wednesday we'll do this kind of like one property at a time here Thursday Friday and then Saturday right so there's our days of the week going across the top now let's change our icons right we don't want it always to have the same weather like let's let's look at some different weather and for that let's go back to SF symbols so here we are in SF symbols and you can

start to see in feel free to pick any weather you want you don't have to pick exactly what I pick I'm going to go with uh Sun Dot Max fill command shift C to copy that we'll go back to xcode here and I'm going to paste that here and you'll see it update like right away so command V bam there

you go you see Wednesday now Sunny I'm gonna make Thursday uh windy I don't know what that means so let's go back to symbols uh here's wind and snow yeah let's go wind and snow it's quite drastic changes here uh in this climate so uh command shift C to copy that back to xcode paste it here there you go a little snow and wind let's see what else we got here in SF symbols

um I'm gonna go with this sunset here here command shift C for Sunset fill again pick whatever you want you don't have to do what I do but you can kind of see this coming together right there's Sunset fill and then it's going to snow on Saturday that's that's what we want just flat out snow right it's getting to be that time of year actually you know what let's go that rain's

not gonna this is the tricky thing about picking your background color is that rain blue probably won't show show up so uh you know maybe an issue we have to deal with later anyway pick the snow uh come back here to the snowflake command V there you go now it's snowing on Saturday now let's change our temperatures just to kind of reflect that it's gonna be really hot on Wednesday let's

say 88 degrees uh Fahrenheit for those in the U.S here Thursday it's windy it's going to cool down to 55. Friday is going to Sunset we'll say it's 60 right and if it's snowing on Saturday man it's

to 55. Friday is going to Sunset we'll say it's 60 right and if it's snowing on Saturday man it's down to like 25 degrees quite a drastic change but you can see our weather app is now starting to take shape one thing you may notice is that we picked all the way back in the beginning right we picked white for our array well now you can see that white is starting to clash with the white of

our text it makes it kind of hard to read we can create a custom color because I think a lighter blue would look better right so in at the top we go from just the normal blue and then at the bottom we go to just a lighter blue so that makes the gradient more subtle so let's talk about how

you can create your own custom colors so over here in your XC assets just like you were dropping in an image down at the bottom you can hit the plus button hit color set and then here you color you any appearance dark appearance this is for you know light mode dark mode Let's do any appearance because we're not going to mess with dark mode in this current APP and bring out your toolbar on

the right if it's gone and here you can pick uh you know your color gamut you can pick whatever color you want here so we're going to try to get a light light blue and I'm not going to have like an exact you know value here you can just see it changing colors up there and pick what you

want so we're going to go like very subtle light blue and maybe a little more we can test this out and see it so but the key here is when you click on color you want to name it right so we'll say light blue right you can name it whatever you want and usually in an app you're gonna have a lot of

custom colors typically so what I like to do is down here hit plus folder create a folder called colors change that colors and drag light blue into colors that's all we're going to make for this one but it's a good habit to get into so back in our content view now we have a color called light blue let's get rid of the side panel we need the we need the screen real estate so instead of color

here passing in dot white we can do color and then initialize that and you see we can initialize that with a name and here we're going to name it uh light blue whatever you named your color right and let's do a command B to get this to run because right now it looked like I put a gray down there

oh I gotta hit resume on my preview that's going to get you a lot there you go now it's like a more subtle light blue you can see go from dark blue to light blue almost has like a teal feel to it but our white colors stand out a little more maybe not much but a little more now if you look at

our design our H stack is not way down there right we gotta have room for a button because we're going to be changing to day to night mode later so instead of a spacer in between our H stack and our big weather temperature let's delete that spacer and see what happens so we're going to delete that okay I pushed it up so it's a little cramped obviously right it's

cramped right up on there but what we can do is we can put a padding bottom on our v stack here that has our huge icon in huge temperature right that would be this v stack right here so we can do dot padding and pass in specifically on the bottom top bottom and comma we can give it a

value again this is where you just kind of dial it in say 40. and that looks about right I mean I literally just pulled that out of my butt but uh yeah that looks about right and then you got the bottom down there now of course uh you know if we were going really deep into this and we

had to you know account for all the screen sizes super small you got to be a little more thorough but again this is the intro video what when baby steps right but now you can see it's starting to be spaced out nicely and we have room for our button which we're going to add in the next video all right so our you guys coming together uh we're gonna add the final piece which is the button just

the UI of it then we're going to refactor and then in the next video I'm going to introduce State and how we can switch from night mode to dark mode and change things based on State and pass that state in a binding down to another view we're going to start dipping our toes in passing data keeping it very very simple but again it's just the beginning so let's get to it all right so down

at the bottom here again remember this whole thing is a v-stack right on our design so the last piece of the z-stat or v stack I'm sorry vertical stack V is our button so after the spacer that goes uh after our H stack which is right here let me make some some room here we're going to create our

button and to do that it's just button and button takes in two pieces right you have this first kind of uh closure here but then there's a second one you do label right so the label there's a couple different ways to initialize a button this is what I found is the most common because this first section here is the action it's what the button does right so what we'll do right now just

print tapped this is where we're going to change from day to night in our UI but for now button tapped label is what the button looks like right and it's kind of different from UI kit we're in UI kit you're actually customizing the button itself well here you just kind of get the functionality of a button and you can make it look however you like so for example our button label is actually

going to be a text that says change day time you name it whatever you want and you can see we got our button down at the bottom now what do you think we're going to put below that button to get it off the bottom of the screen we don't want it down there right we're going to put a spacer

down there so one more uh spacer now something you need to keep in mind when building spacers on a and I'm curious if I'll run into it no uh on a on all these views is the spacer counts as a view and one restriction on purpose of Swift UI is that in this whole z-stack right in the the overall view

you can only have 10 views as soon as you put in your 11th view xcode is going to yell at you and say you know you you can't do this right so if we count ours we have our gradient background view cool we have our v stack right now nested stuff doesn't count right so linear grain of you is

one our v stack with our big icon is two uh our H stack with our days is three the spacers four the button is five and this last spacer is six okay so we're well below the ten no big deal but something when I was learning Swifty why that I kept running into is you know I'll admit my mistakes right I

was overusing spacer right you could argue I'm even overusing it here too and I was hitting that like 10 view limit a lot so something to keep in mind spacers are great but you can easily kind of overuse them and kind of run into trouble there and real quick the solution to that 10 view limit is the refactor your views right refactor it out into another H stack here refactor it out

into its own separate v-stack you know so there's easy ways around it through composition so I don't want you to think that like it's super limiting it's to prevent you from creating like Swift ui's version of massive view controller and you know you don't create massive view right it forces you to kind of refactor that so anyway now that we put our spacer down here at the bottom you can

see our button is up higher but we just have the the default button layout right we don't want that we gotta make this look pretty good right so first thing I'm going to do is give it a frame and the width is 280 and this is just 280 by 50 is kind of like my go-to button frame um and you can

see the the red outline down there of what it is and to be honest with you that's kind of like the the typical default Apple button nowadays right it stretches out the screen it's pretty thick easy to tap um so now you can see our frame let's give our frame a a background color that background and that's going to be color dot White there we go so there's our button and uh let's actually I like

a big bold font on my buttons personal preference you don't have to do this one if you don't want to so we'll do font and you're going to dot system hard code it and we'll say 20 of dot bold and design.default there you go it's a nice big chunky bold font and then the the final piece of the

design.default there you go it's a nice big chunky bold font and then the the final piece of the puzzle here is rounded Corners which you can't see because of this red outline but if I click somewhere else right you see it's a very blocky button again I go for the default apple look gets a little bit of a corner radius so the modifier for Corner radius is Corner radius dot Corner

radius and real quick it may seem like there's there's tons of modifiers and it's going to be impossible to to memorize those however there's a group of them that are very very very common that you're gonna like frame font background color Corner radius you'll get very familiar with those but you know I could go through modifier by modifier making a video for each one I feel like

that's kind of a waste of time uh you'll you'll you'll learn and you'll pick those up over time as you use them so let's make this corner radius 10 and if I get rid of that red square now you can see our nice Apple default looking button so our UI without the whole night mode stuff uh is done

great what'd you think how'd that go right not not so bad again I went very quick but we're going to dive into a bunch of different apps we're going to do this over and over again um I'm very confident you have the hang of the UI part uh at the end because if I'm being honest like the UI part the

HDX the V Stacks like that's kind of the easy and fun part of Swift UI it's the passing the data that really trips people up so that's what I want to focus on but anyway UI is done uh let's start refactoring this thing so let's start from the top in my big disclaimer here is Swift UI is so early how you structure how you refactor how you compartmentalize your code like a lot of us

iOS developers are still trying to figure out best practices so I'm kind of figuring out the way I like to organize I will you know give the disclaimer that if you ask me in two years I'll probably be a little different you know best practices will be established however I do think this initial way is a good way to start and then hopefully you and your learnings can evolve as the

Swift UI best practices evolve you're just super early that that hasn't really been as established yet so starting with the linear gradient we're just going to create a view called background view right so command click and you can see the extract sub view down here so now we just have extracted view let's go down to our struct here at the bottom you see we got our extracted view that

we just kind of did that well I'll do the next one manually so you can see how both work because to be honest with you sometimes that extracts sub view is a little wonky and it doesn't work all the time so I usually end up doing it manually anyway but I wanted to show you that so we'll probably do the rest of them manually but let's call this background view here and okay let's

talk about what we want to pass in here because if you look at the design here night mode has a different gradient so we want to be able to pass in the different colors right so uh we wanted to pass in you know blue and light blue or whatever the colors we need so we probably need variables

here right so VAR call it top color and that is a color that we pass in and let's call VAR bottom color and that's a color that we pass in and then let's replace this with bottom color comma or I'm sorry top color top color goes first top color comma bottom color there you go so now that view

is refactored and we will now replace you know all that up here with instead of extracted view let's call it background View and I'm going to tell you why here as soon as I'm done with this uh why this is helpful and makes things more readable here okay looks like I lost my autocomplete here let's see what's going on with background view um okay I silly mistake here this is the problem

when you're kind of like talking while coding so I put variables inside the variable called body you cannot do that so what needs to happen as you saw that we did up here with whether debut those variables and properties need to be on the struct itself not in the view so I just I put them in the wrong spot because I was talking and explaining kind of half paying attention so now

if we do command B that should be all good down here we still got build failed because our code is messed up at the top but background view here is now good to go now that the properties are are on the outside small little missed up there so background view uh this explains why I wasn't getting my initializers here so let's try to type that again I always my habit like if I don't get

the autocomplete I don't feel good about it right so I like to make sure I get that autocomplete so background view down here and there you go top color bottom color so let's pass in dot blue and pass in dot uh color with the initializer of a name called light blue and even though this may seem like it didn't save a lot of lines of code and it's very similar to what we just did

well one you're going to see the flexibility we introduced when we go to like night mode but two it just makes your your screen read a lot nicer right background View top color blue bottom color light blue cool pretty simple uh you get that and then as you rename your other views that you refactor your your screen is going to read quite nicely all right let's keep it moving here

this text we have our city name so we'll copy and then now we're going to start doing this manually here and for now I'm going to put all these in the same file I'll get I'll talk about project organization after we get it refactored and how we move stuff around that'll come in a little bit so let's do struct we'll call this uh City text View and it conforms to view and then if you just

start type VAR body you'll get the autocomplete so body some view there you go that's the same structure and now if you look here if we want to make our city text a little bit reusable um we just need to pass in the text right the city name so here the variable on City text view can just be VAR city name that is a string and because I've already copied that text view I can come down

here do paste right so instead of Cupertino we can just do city name and now this is uh reusable so back up and then now you're going to start to see the readability here so instead of just this glob of text City text View and pass in the city name and now we can do Cupertino California I hope I

spelled that right we'll see hit resume on our preview just to make sure I always like to do it a lot do a command B to make sure everything is all good and looks like we're good nothing changed but now you can see how our screen is reading uh a bit better so now let's uh refactor out

this v-stack that is our main kind of uh weather so again I'm going to copy this and down here at the bottom we'll create another struct again this is kind of probably starting to get repetitive but you'll see that all this repetition is really going to help you learn how all this stuff works and this is the first step of this right because right now we're just refactoring out the views

but eventually when we're passing data around we got to make sure these views have all the correct data so I want to make sure you understand how to refactor these views before we add the more complex step to it right so we'll call this main weather status view naming's hard if you've if you don't like that name name it whatever you like that's fine so if here's what I like to do here

um first we'll do VAR body before I do my variables I like to paste what I copied in there right I copied and paste to this and by looking at this I can see what variables I need right like I'm going to need an image name right because that's it's not always going to be Cloud Sun fill so VAR image name and that's a string cool now I can plug in uh image name here and it

looks like I'm you know my my temperature is going to be dynamic so same thing we did up here with the weather day view temperature is an INT so I'm going to copy that I mean you could type it out if you like but I'm going to paste that looks like I forgot to copy the V all good so far temperatures in int and again just like we did before very similar string interpolation temperature

cool so again now up here in our view clean this up a bit we can get rid of this v-stack and just call this main weather status View completion here string we want the image name to be cloud and I'm just looking I'm just looking down here to remember what it was uh cloud.sun.fill and the

temperature 76 right and again if it gets too long feel free to bring your variables down like that I like to do that um Okay cool so now let's make sure do command B I always again command B after I refactor make sure everything's good make sure my preview is right cool again now you're gonna you're starting to see the readability I have a z stack with a background view now I have a v-stack

with the city text view the main weather status view a new developer coming into this screen is going to really know what's going on based on how you structured your refactor here now this is where a debate could come in and I do think you can take what I've been doing I do think you can take that too far so there's like a balancing act for example I kind of think leaving this hdac

even though it takes up a lot of code right remember the goal is the goal is not to be like let me get my content view to three lines of code right because oftentimes getting it that short makes it a little hard to like understand I I kind of think that leaving this hdac you know if we didn't have an array with our data and passing an array that's a totally different

thing if you're familiar with swift UI you know what I'm talking about but in this circumstance I think this makes it very clear what this is on the UI right because you have five weather day views it's pretty pretty straightforward what's going on here yes it is an extra 10 15 lines of code that you you could refactor out but again getting down to three lines of code is not the

goal making it easy to read and understand is the goal so I'm going to leave that there I'm going to leave the spacer here and one thing I like to do with my buttons here I'll first get rid of the space I don't like that so I'm going to refactor this text out into a button and I do this with my buttons because again this is like a default looking button right you're probably

going to use this type of button all throughout your app so again let's create another struct down here at the bottom and like I mentioned we're going to do some project organization next these can be in separate files but you know I'm putting them all here for now so not VAR struct let's call this uh weather uh button and I just like to kind of put like what type of app it is

usually it's just like like essay button you may have seen in my previous videos for Sean Allen button or G GF button for GitHub followers button in my previous course um so I like to put something about the app in in the beginning of it uh that is a view and again VAR body some view you're going to type that a thousand times you'll be very used to that and again I paste in

here to see what variables I need Okay so let's look so I'm going to need a title that's for sure so VAR title it's my button title that's a string so let's change this uh here to title and zoom up here now I'm probably going to want to change the background color and most likely the foreground color as well but you see I don't have foreground color here so let's do type foreground

color which put in dot blue for now that's what it is as the default but let's actually make these variables here so VAR let's say text color just to make it very clear that is going to be a color and then background color also a color right so instead of background being color.white it's going to be background color nope kind of The Perils of naming your stuff close to the default stuff

here uh and then text uh color right so on our weather button we're going to pass in the title text color background color that makes it so I can reuse this button in a lot of different uh contexts here so again up here instead of this button we're going to do weather button and then

we're going to pass in the three parameters right title is change day time text color is dot uh blue and background colors dot white and again you can leave it one line if you want my text is so big here that I'll put that you know on three so again now you can see our button what it does it's just going to print something for now we're going to fix that it's a weather button with

the text title color background color so that's reusable so that is like our our very first pass at refactoring so you can see how to extract the views into their own struct which again I have the whole list of them down here right the weather day view the background view City text View weather status view now when it comes to organization I want to talk about this I'm not

actually going to create new files and move them around but again like like this is a standalone struct as an example weather button like actually you know what I am going to do that I lie to you little ad-lib on the fly so I'm gonna do command n in the Swift weather do a new uh Swift file hit next call this weather button and the reason I'm doing this for weather button is because like I

said weather button is the type of of thing that you are going to use all throughout your app right that's very reusable your button should all look the same or similar so that is something I want out of this file and outside of it right now if I do a command B well it's going to say uh oh I didn't import Swift UI import Swifty I copied and pasted over over some important stuff

then you see invalid redeclaration that's fine that's expected that is because I still have it here but once I delete that there done so again on the topic of project organization as that example if a view that I've refactored out is going to be used all throughout the app and elsewhere definitely I put that in its own file however if a view is very unique and specific to the current

screen that I'm on but I just refactored it out to make my my screen more more readable and easy to understand like you see here then I keep that in the same file right so you get that distinction if it's Unique to this screen I recommend keeping it in the same file because it's easy to find less

confusing if it's going to be used all over your app or in other screens of your app put that off into another file all right so that's the refactor in the next video we're going to dip our toes into actually passing data it'll be pretty simple but you'll get to start seeing how swift UI handles view updates based on a source of Truth with data getting ahead of myself let's go to the next video

we left off last video with a bit of refactoring and dipping our toes into project organization which we'll we'll get more in depth later in this video we're going to introduce the passing of the data and changing from day to night like you see in this video uh based on a Boolean and start talking about state in Swift UI all right back to our code our weather day view that we

refactor let's go back up to the top let's add a what's called a state variable and I'll give you the quick explanation but like I said the the bulk of this course is going to focus on you know at State at binding at State object add observable object passing the data so this is like just the very first steps of it so uh don't convert this took me a long time to wrap my head

around all the data flow in Swift UI so in this app if you leave this being like I have no idea what's going on don't worry we're gonna Hammer this home over the next couple apps and throughout the rest of the course so State private VAR is night and that's going to equal false by default right so do command B to get rid of any errors here okay so big picture again we'll drill down

later the way Swift UI works is you don't directly update UI you tell some source of Truth some piece of data in this example that source of Truth data is this Boolean is night so you set up your UI to handle if is night is true and if is Knight is false and you can imagine we're going

to have change our background color base based on is night true or false so your UI is waiting for that change and when that change happens your UI is like watching that source of Truth and when that change happens your UI will change like it's reacting to it right this declarative programming versus imperative programming I have a whole video in the next section all about that but that's big

picture keeping it simple so what we need to do is set up our UI to handle both cases like what happens if is nine is true and is Knight is false okay so what we're going to do is just change the top color and bottom color on our gradient view if you're familiar with ternary operators we

can do is night and then if it's true through we'll do dot black and if it's false we'll do dot blue right that's just for our top color and then for the bottom color because this is going to get too long again let's put our parameters on a separate line here so same thing is night and it's going to be dot gray and if it's true and if Knight is false it's going to be light

blue so if his Knight is false it's going to look just like we have it here however if is Knight is true we're going to change it to black and gray so let's try this out here down in our button remember we just did button tapped now we're actually going to flip that Boolean so we can do is night dot toggle so every no not custom mirror what are you doing xcode toggle all right

so now when I tap the button it's going to just toggle from True to false and based on that our UI is going to be watching it and it's going to adjust our background gradient accordingly right so you can either run this on your device if you want run it on the simulator or the nice thing about previews if you hit this play button and you'll see the background will change to this like

grayish blue kind of thing that means your app is like actually running and you can interact with it so watch what happens when I tap the change daytime button bam now it's into night just like that so what's happening is right now is Knight equals true when I tap this is Knight equals false and now my UI knows that that source of truth of data changed and then it updates accordingly now

let's make some small tweaks here so if I go back tonight well it's still sunny and cloudy at night well that's that's a little weird so let's go to our main weather status View and the same thing we can do here right we can do is night uh if is night is true we don't want Cloud Sun fill we

want moon stars fill right you see it here or you can do just moon or whatever you want who cares right Sparkles whatever you want to put in there I'm going to do uh moon stars fill back to xcode do command V to paste that in there so now if is night is true we're gonna show the moon if

it's false we're going to show the cloud Sun hit change daytime and you'll notice I didn't have to stop my preview and restart it right it just it's it's hot reloading the code so this is the nice thing about previews when they work but you see now when we're going from day to night we're also changing the icon back and forth right so that's pretty cool so that is the very very basics of how

Swift's data flow works again you have a source of Truth your data model and when that changes your UI updates now the trick is is making sure you set up your UI properly and making sure the UI is you know listening to the right stuff to update you got to make sure your model objects is publishing its information you got to make sure like things are listening so that's kind of the tricky part

of it again we'll get to that one last thing right so we covered State now let me give you I'm going to dive into this later but real quick the reason you put State variable in front of it is if you're familiar with your structs versus classes like Swift 101 structs are value types so they don't hold state right they get destroyed and recreated so how can you make a struct hold State

well that's what this state property wrapper is for right so if you can imagine this view called content view is just a struct and it gets created and destroyed all the time created and destroyed that's what Swift UI is all about very cheap views that get created and destroyed redrawn all the time however this little piece of this View you called is night this little piece of data this

Boolean has state in front of it so that means that gets put off somewhere else to keep that state while the rest of the view is constantly created and destroyed this keeps state so super basic explanation but hopefully your mind is starting to see how like Swift UI Works a little bit okay so now on to that final piece I'm going to talk about we're going to refactor background

view even more so we don't have to like this is kind of like messy and it's going to introduce binding okay so let's go down to our background view okay so we don't want to use this we don't want to pass in a top color and a bottom color we want to pass in VAR is night and that is a bull

now this is night needs to keep State like we just talked about right it needs to always know in my day and my night what am i showing because again this view could get recreated and destroyed now this is night variable always needs to match this is night variable right because it's the same thing right this view is a child of that view right we're passing this is night variable down

the view hierarchy to the children so they need to be the same at all times right so that's what binding is for so if I put binding in front of at here so binding VAR is night and then we're going to have to do that logic here where is night we this is what we just did before dot black if is

Knight is true if is Knight is false we do dot blue and then let's delete top color because we're done there and same thing with bottom color again is night if that's true we're going to use for the bottom color uh dot gray if it's false uh color initializer name remember this is exactly what

we did uh up top you could even copy and paste it uh if you like so that way every time we use our background view like right here every time we use background view if we're using this you know all throughout the app we would have to pass in these kind of colors well now background view just takes

in a binding right is night but you can see it's not just the bull right it's a binding bull so I can't just put is night right because that's it's not binding because down here in the background view I specifically said this needs to be binding and again what binding does is makes it so my is night variable on my background view is always the same as this is night variable right so to do that

you put a dollar sign in front of it so that makes it binding so now I'm passing into my background view a binding to is night right and then now here so that means on my background view this is night is always going to be the same as this is night that's what binding does so back down in the in

the background view we should be good to go here and then again it's just a little cleaner up here just background view is night you pass in is night so let's uh stop stop this [ __ ] to be sure rerun the preview and now if we do this should work the same yep it works the same and that's a very basic

example I just wanted to introduce the concept of binding and how when when passing it down that's the key passing it down the view hierarchy to the children right because the background view here in in this circumstance is a child of the content view right it's part of the content view so we can pass the binding down the view hierarchy now in more complex apps you can imagine like you could

be passing a binding down six views down the view hierarchy to use it there's other ways you know things like the environment you know we'll get into that later but again this is the basic introduction of state and binding those are the two most basic ways to pass data we're going to be doing that a lot throughout the rest of the apps but this is your introduction so that finishes off

this weather app I want to leave you with some some challenges uh that you can take this app in and go even further with it another challenge you know and this is more towards those who have experience building building Swift apps uh create a data model that you don't have to individually pass in this stuff right you can have an array of like a day right in a day would have you know a

day of the week a temperature an image name or maybe a weather enum that you pass in that has the specific image attached to it you can make this neat and represent a data model uh that's a bit more not it's not advanced it's kind of basic iOS knowledge but if you are like a super beginner just learning Swift UI that may be above it but if you have app experience you should be able to do

that so that'd be a good challenge and then if you really want to take this far uh create a network call from a basic weather API that will take whatever City you want and it'll actually give you the next five days of weather that's taking you pretty far but my goal here is to give you the basis of an app that you can tweak yourself build upon all that good stuff or maybe you

put a tab view that shows five different cities based on that API I don't know have a ball with it here's the basis those are some challenges you can do to push yourself and if you have questions about those challenges uh feel free to ask in the slack Channel I'm sure plenty of people will help you out so that wraps up the weather app and again if I went super fast you felt like I was

throwing a lot at you this was just so you could see it in action in the next section I'm going to do a lot of talking head explainer videos that do a deep dive into a lot of the theory and the concepts but again because you've seen it in action now when I explain that stuff hopefully that connection can be made whereas if I just started off explaining things and you've never

seen it in action it's kind of confusing so again that was the purpose of this just to give you a taste of it in the future apps you know we're going to go a little bit slower we're going to dive into a lot of the details uh and you're going to get a lot of practice and repetition

because to be honest with you a lot of it's the same when it comes to like the UI and stuff in this video we're going to update the weather app for iOS 15 and fix some issues we had before now this is a pretty basic app so the only new iOS 15 thing we're going to explore is the new

SF symbol stuff but I want to clear up an issue with binding that I originally did on this app that will maybe clear things up and then we'll talk about some deprecated syntax that usually happens when a new iOS version comes out okay so here I am right where the project left off so hopefully you're in a similar version than I am but the first thing I always do anytime a new iOS

comes out is you click on the project here right and then now you want to Target if you click on Project iOS deployment Target iOS 15. now again this makes your minimum Target iOS 15 like I said in the iOS 15 update overview very very few apps can actually do this usually they have to support iOS 14 maybe even 13 but again for checking things I go to iOS 15 because then I'll get all

the errors if I'm using stuff that like doesn't work and again this is a super beginner teaching app so we're not worried about supporting like all older iOS versions the whole point of this is to show you the new stuff in iOS 15. so now that I am supporting iOS 15 I do a command B to do

a build and doing that will show me any errors or Warnings that I have you can see I have two errors up here let me go to iOS 13 Pro here maybe that's the issue here I'm not sure what errors I have yeah those errors were because I was on not on an iPhone and it didn't quite get it so make

sure you have the iPhone 13 in your simulator to clear that up okay so into the content view the first thing I want to talk about is deprecated syntax because like I said this happens every iOS update usually you'll get a warning for them if they're like being close to actually like not working anymore but what's deprecated and actually we'll go down here this was actually deprecated

in iOS 14 and I missed it and that's another lesson is like you're not going to catch all the deprecations right away let me back up because this is a beginner course what does deprecating even mean well you know Apple will change the language of Swift or Swift UI and you know they'll try to constantly improve it so sometimes they'll change the syntax of oh my language and you know

just change the way you do things the good thing here is when they're deprecating something they'll usually give you like a couple years warning so for example like this Edge is ignoring safe area still works great you don't even see any warnings that's what I'm saying so that just happened last year so probably in like a year or two you'll start to see warnings and then maybe another year

after that then they'll finally break your code so don't worry about deprecations too much it's great to stay on top of them and not like wait for it to break your code but like I said Apple does give you plenty of warning and we can see that if we option click on ignore safe area and go into open developer documentation you can see on the right deprecated now you may be wondering

like well how do I know if it's deprecated a lot of times you got to look in like the xcode release notes in the iOS Developer world after WWDC in like uh June so from June to September xcode betas are coming out everybody's looking at the documentation you're seeing all the new deprecations a lot of people are talking about them on Twitter so unfortunately at least not

that I know of there's no like centrally located list you can go look at I guess keeping up with the xcode Beta release notes will show you but like I said try to keep up with them that way but if you miss one or two it's not a huge deal and then again in probably like a year or so you

will uh get the warning that tells you this has been deprecated check out the new thing so the new thing is ignore safe area and like I said this was deprecated in iOS 14. so I missed this one but again no big deal if you missed it come back and fix it so that's just the big picture lessons on deprecations and with Swifty why because it's so new it's so young you're going to see a lot

of like changes early on over time as it matures that will slowly happen less and less but again we are in the beginning so you kind of gotta expect that uh to happen now the next thing I want to point out since we are in our background view Let me refresh your memory we were factored out this background view which again is this black and gray here gradient for example I'm gonna go to is night

equals false to go back to the blue and there we go I like that look better so uh we have is night is false now you see this background view which is what I was talking about we passed in is 9 right now if you're doing this course for the first time this should be very fresh in your mind if you're

coming back maybe it's not so fresh but what we did here in the background view is I passed a binding down to is night we don't have to do that in this case to be honest with you I'm not sure why I did that here but this is a good learning opportunity good chance for me to actually show you uh more of what binding does because anytime you do something wrong and then you come back and

fix it usually you learn it more that way rather than doing it right the first time as weird as that is so we messed this up before because the whole purpose of binding is if in our background view we're going to change this is night variable like maybe if we tapped our background view we changed it from is night to true or false maybe that was how we changed the background then yeah

binding would be good and we would have to change his Knight down here in our background view but because we're only like reading I guess if you think about read write right we're only just looking at what the value is and then adjusting our background color accordingly we don't need binding right the whole purpose of binding is if we were going to change this variable

because again it's bound to our initial variable up here on line 12. so if we changed it in our background View and it was marked binding this would also change but we're not doing that in our background view so making it binding there's no reason to do that so we'll delete that dollar sign there as well so apologies for the confusion we'll discuss binding more I believe in the

appetizers app we get into it but apologies for any confusion hopefully that cleared it up again only use binding is if whatever view you're passing that value to for example it was our background view you're actually going to change the is night variable because we're not changing these night variable there's no reason to make it binding all right the last thing we're going to

do on this weather app is actually the first new and iOS 15 thing right the previous two things were fixing some mistakes but now this is new in iOS 15 and that has to do with our SF symbols so before we get into that let's look at Safari here and I'll link to this in the description SF symbols 3 is the new thing so you see it added over 600 new symbols enhanced color customizations

which is the main thing we're going to discuss here but check out this link here's what we're going to deal with here right this enhanced color customizations so it got a new hierarchical and Palette rendering so what hierarchical is I'll keep zooming in here to make this image bigger I guess the image isn't getting bigger funny I zoomed out and made it bigger anyway hierarchical

is the second row you see how it's kind of like uh the same color but there's like layers to it like there's like a brighter blue and a dimmer blue so hierarchical gives it layers and if you have the same color with hierarchical it'll look like this kind of like the monochrome look whereas palette gives you full control over these layers so you can make them all kinds of different crazy color

combinations or whatever fits with your app and that's what we're gonna play around with so back to xcode let's deal with that here and we'll do that in our main weather status view right where we have our image what we're passing an image name which again is the SF symbol that we pass in which we did up here right how we did you know wind.snow sunset.fill snow right so that was just a quick

little recap but we're basically just going to mess with the modifiers on this image right and you can see the little red squares on my preview you those are the images that we're dealing with here so we did rendering mode original to get the multi-color so you don't want to mess with that anymore you want to do that symbol rendering mode and then you're gonna see here if you do

a DOT you can see the options so we just talked about hierarchical multi-color palette so if we want what we have now we would do multi-color do a command B nothing should change because that's what we have okay now let's go hierarchical and then we have to give it a foreground color but you can see it's black by default and you can already kind of see the layers I'm going to zoom in really

close to our SF symbols here right you can you can already see the layers even though they're black if you want to change the color got to do it after resizable do foreground color let's say dot red and those will change to red and you can see the depth right we got really bright red and then like a 50 opacity red and real quick the reason you have to do this after resizable is

because the resizable modifier is only on an image so as soon as we put a foreground color modifier before that you it won't be an image anymore it'll just be a view you and a view doesn't have resizable I believe we get into that in a little bit when I talk about modifiers and how you're just building like layers and layers and layers so that was a little preview you'll see

that uh in a little bit okay now let's mess with a palette because palette is the pretty cool one right so palette here nothing well I guess it did change everything's all red so a palette has three colors you can give it so instead of foreground color we'll give a foreground style and then you can see actually that's not the initializer I wanted so I want to do foreground Style

and then like look so that was just one color but you see we got primary secondary primary secondary tertiary so this will give you three colors and here's how this works because some of these shapes I think ours are only going to have two but some of our SF symbols have like three layers of palette so you got to give it three colors so uh we're gonna do dot mint

dot orange and then dots uh green for our third one so the first two colors right if if your as a symbol only has one layer okay mint's a bad color you can barely see that um I guess we'll do pink here so like I was saying if your SF symbol only has one layer like our Wednesday Sun that only has one layer so that's going to give you the first color which is

pink if your SF symbol has two layers which you can see Tuesday Thursday Friday has two layers well the second layer is going to be orange so you can see how that works and then I don't think any of ours have three layers no but some of the SF symbols do have three layers so that's what this third color will be so you can see if you have a certain like brand uh color scheme going on

you can change your SF symbols to have different layers to match that color scheme so big picture we're just getting a lot more control over the SF symbols and again if you uh just want more of the same color look uh hierarchical and then you don't do a foreground style you just do a foreground color and then we can do dot pink and then that'll give us again that kind of uh

Pink layered look right there hit resume on the preview just make sure we're good but that is uh new in iOS 15 new NSF symbols uh again SF symbols are constantly growing year over year they're getting better and better and better I love them and just the addition to completely customize the color is a super good one so that's what's new in iOS 15 and the weather app let's move on

here I am in the weather app where we left off at the end of the iOS 15 Section you can tell because the colors of our icons are all messed up so first thing we want to do go to our project project here minimum deployment Target is IOS 16 and same thing here in your target iOS 16. there we go do a

command B make sure everything is okay cool build succeeded go back to our content view get preview back up and running cool everything looks good let's fix these colors real quick they're they're bothering me here so rendering mode back to multi color and we'll just comment out this foreground Style just so you can still see the code but we're not gonna mess with that obviously okay

let's talk about this gradient here so we have our gradient view our background view I'm sorry that is our linear gradient iOS 16 introduced a simple modifier dot gradient that will give you a default very subtle gradient now I want to stress it's the default one so you can't really customize it right so when you make this linear gradient view like we did as you can see you can customize

the exact color you can do the starting point the end point so to be very clear if you need a super custom gradient that you want to mess with you're still going to need to stick with this however on things like buttons or certain views a default simple subtle gradient works perfectly that's what I'm going to show you we're going to do it for our background and we're going to do it for our

button so I'll comment this out so you can still see that and you still have the code here and we want to do a container relative relative shape and we want to give this a DOT fill you'll see so there it is there's a shape it's just black but we want to give it a fill and we want to do color dot

Blue Dot gradient and I just want to show you this first let's actually do dot ignores safe area so it fills the whole thing up so you can see it's a very subtle gradient you might not even noticed it let me go back to line 105. let me delete gradient so there's just blue okay so look look at the top

part of the screen and then dot gradient so you can see very subtle but this is Apple's default gradient that they use all throughout their system now of course we don't always want blue right we want the ternary operator of is Knight if Knight is true we want color dot we're going to do black dot gradient or color.blue.gradient so now let's tap change daytime that goes tonight and again you

can see the subtle gradient it's actually more prominent on the black you can definitely see the gradient but maybe you don't want black maybe you want gray and I'm kind of trying this in real time oh change time of day nope Gray's too light yeah we'll do black but anyway again this gradient may not work maybe you do want the more custom gradient where you

can customize the angle and the specific colors for that you would still need to use this linear gradient however if you want just a simple subtle gradient and just a simple modifier of dot gradient this is a great way to go let's do this on our button too let's go to weather button here so instead of background color we're going to do background color dot gradient that's

what I like about it super simple you just type dot gradient and you can see the subtle gradient that we get there now if we go to our content view for our button here we'll scroll up to our button there you go where we have the title text color of blue let's do background color of because you can't really see the gradient on white let's try dot mint and text color of dot white right you

can play around different color combinations but that's how you can see the very subtle gradient on the button so that's the new way in iOS 16 to do gradients again it may not suit your needs that's fine use the old gradient and customize it however if you're just looking for a super simple gradient this is beautiful I know I'm going to use use this on a lot of buttons in my apps

now that we've coded a bit and seen the basics of Swift UI in action the next few videos are going to be a couple of explainer videos just kind of talking about how swift UI Works kind of in the in the big picture sense to help your mindset maybe shift to thinking in the Swift UI way and after you have the basic understanding from the next few videos we'll get back into

coding to put those principles into practice okay so this first video is going to be talking about declarative versus imperative because if you're coming from the UI kit world that's likely the methodology you've been using uh in your previous iOS Developer career now like I said Swift UI is declarative it's a whole different way of thinking and to be honest this was this is

probably the hardest part of coming from UI kit and learning Swift UI is getting your brain to switch because as I'll explain in a second like the way you think about things is kind of like flipped on its head a little bit I know this was like one of my biggest struggles because you know I've been doing UI kit for about five years now so my brain is just you know in the

habit that muscle memory of just thinking that way and like I said you have to like change the way you think I know I've said that before but it's it's kind of tough to to break the habit and it was only after a lot of practice a lot of frustration a lot of headaches that my brain you know finally flipped and to be honest I don't think it's like fully flipped I

still revert back to that UI kit way of thinking sometimes but I'm getting there okay so I've been throwing out this imperative declarative words you may not know what that means so let's break that down so imperative like I said is the old UI kit way of thinking and in that methodology you are specifically telling your UI what to look like all throughout the execution of your program

so that means there's there's like two code paths right there's the code path where all your logic is changing you're changing all your data and then as you're going along that path changing everything at every moment in time you have to be telling your UI okay UI something changed Now update okay something else changed update right you're managing these two code paths your logic

in your UI and they always had to be in sync and that's a lot easier said than done and this was the cause of a lot of bugs well declarative gets rid of one of those code paths entirely right you've heard me mention in the previous videos all we do in Swift UI is update our data in our UI response accordingly now that sounds like magic the way I just said it but here's how it actually

happens right we declare or we give all the rules for our UI up front right we give all the possible States our UI can be in that way when we change the data our UI just follows the rules we put in place and shows the proper UI now if that was a little bit confusing let's go back to our weather

app and I'll really break this down so here we are in the app and again super basic example right our only piece of data really is this is night variable that we flip from true or false and what I meant by how we set up our UI for all the possibilities up front well luckily for this simple example there's only two possibilities is night is true is night is false and this is what

we just did right in our background view let's go to that down here where we built that here right so here on our background view we've already set up our UI ahead of time right with our gradient changing our colors based on is night you know it'll be black or blue for the top color or it'll be gray or light blue for the bottom color depending on is night so again our UI knows ahead

of time like every possible state it can be in we've already set up the rules right same thing for our main weather status view right where we either show the moon or the cloud in the Sun we've set up the rules for both States it knows it that's why that code path where you're updating the UI completely goes away and you don't have to worry about your UI always being in sync because

if you set everything up correctly all you do is change the data source there is night to true or false and rui just follows the rules and it knows what to show so that's just a super basic example with one piece of data a Boolean true or false but hopefully that starts to get your mind seeing how declarative UI Works versus imperative right we're imperative you are specifically telling the

UI when and how to update when the time comes declarative you set all the rules up front you said all your States up front and then you just change the data and the UI acts according to those rules in the next video we're going to talk about Swift ui's view trees and how views get updated when we flip the isnight Boolean you know to true or false because it doesn't redraw the

entire screen it only redraws some of it so that's what we're going to dive into in the next video now let's do a bit of a deeper dive into the concept of modifiers but the key takeaway like I mentioned in previous videos like as long as you understand that every time you add a new modifier under your view you're wrapping that in another view and because of that the order in which you

put your modifiers uh on matter so we'll take a deeper look at that but that's really the concept at a high level so back in our weather app as an example let's go to our weather button and one thing that you may not have is I created a preview for a weather button so just copy that text put it

in there to get a preview so we can actually see this while I'm talking about the modifiers so like I said the order matters and I Illustrated this before but I'm going to show it to you again so on text we have our frame modifier right if I put the frame modifier last so if I do command X and down here well what happens is now that background and foreground color happens on the text itself and

then the frame gets added after the the colors have already been put on right so I'm going to put that back and kind of walk you through how this actually actually goes right and then I'll show it to you in code and then I'll show you some visuals hopefully at the end of this you'll get it so what's happening is here is we have our text then we add a frame to it right then when we

add our background color the background color is actually getting added to this combined view of text and frame then you add the background color now foreground color gets added to the overall combined view of title or text frame background and then you can see how we keep going right font gets added to text frame background foreground right I pictured this circle that you see on

the screen here right like you're just putting new views wrapping around uh the existing views and again that's why the order really matters so now for those of you that like to see it in code like to see what's going on let's go to the content view here there's a modifier that we can put on our z-stacks and our V Stacks called on up here this is kind of a preview we're going to get

more into that later it's not about on up here right now but think of on up here there's an on disappear similar to like you know view will appear if you did appear view will disappear similar to that right so on our z-stack here that's what we're gonna we're gonna use here we're gonna use that on up here and we're going to go ahead and give it that closure now here in

these you can actually write all your Swift code right this is not a view Builder right you can just write any any code you want here to do on up here so we're going to say let button equal weather button and this is just this is just to get a debug print out by the way you don't have to necessarily follow this uh this is just so I can print out the what the views

are doing in the button in the debugger again you don't have to do this if you don't want to but you're going to do a print type of and then button dot body right so we're printing out the body of our button which again if we go back to weather button body is this right here so we're going to print out what happens in this uh part of the code here and we're going to do that

when our z-stock appears that's what onappear does okay and we're going to get a printout in our console here so I'm going to run it on the simulator to get the printout there we go let me move this out of the way move this up so you can see so this is what all this modified content that's what's going on with the wrappers so let's copy and paste this and I'm going to

put it in my my code here it's going to give me all kinds of errors but I think it'll be better if I lay it out this way again you don't have to be following me doing this this is just for explanation purposes so I'm going to kind of unnest this so at every modified content there I'm going to make a new line again for illustrative purposes I'm going to return there

turn turn and then hopefully this nesting makes it easier to kind of like see and understand what's going on but basically this the the principle applies of what I talked about is how every time you add a modifier you're wrapping it in a new thing here it is called modified content right if we count our modified contents one two three four five well how many modifiers

do we have one two three four five so like I said every time you're adding a frame a background a new modifier to your to your object it's getting wrapped in this modified content that you see here so this was for those that like to see it in code again I visualize this you know circles wrapping circles kind of image that you see on the screen here that's how I think of it like as I'm adding

my modifiers that you know whatever new modifier I add wraps all the existing views that I've already built and then and so forth as I go out in the circle now back to our content view I want to talk about two more things here so back to the content view you can see right environment key writing modifier so there are these environment modifiers that are a little bit different than

the normal ones and let me show you them in action so let me delete all this so xcode can stop going nuts here so we'll delete all that on up here uh do a command B so xcode can stop freaking out with all that bad code let's go to our weather button so let's pretend hypothetically again we're just kind of messing with our code we're not like really building stuff let's put a v stack here

and let's say we wanted two buttons in our our button for some reason right this again this is you wouldn't really do this but what I'm showing you is the environment so there's many different ways to use the word environment and Swift UI but for for this environment we're talking about everything within the v-stack and when you have multiple things like multiple text or multiple buttons there are certain modifiers that you can put on the v-stack

overall that it'll apply to all the children like of that v-stack for example foreground color right let's command X that and we'll put it onto the v-stack overall I can delete foreground color out of uh both of my individual buttons and you see our previous okay let's I forgot to add spacing onto our v-stack spacing of 20 just to space those out so you can see but uh you can see I basically

refactored out foreground color and put it on the environment of the v-stack so that all the children of the v-stack will get that uh modifier and to really drive the point home let's do one more font is another one that we can put on the overall v stack and not each individual element if they're the same font of course right if you have different fonts you probably need them to

be different but again that shows you environment modifiers that you can put on the environment of the v-stack hdac whatever to apply to all the children and then lastly there are like item specific modifiers like text has a DOT bold all right so let's get rid of our font modifier real quick to show you how each individual one can have it because it has to do with text weight

so that put us at our default font weight well modifiers that are specific to like a text like for example bold is one of them dot bold right you can see now that made our our title bold that was actually kind of hard to see but I'll comment it out and re-comment it so you can see the title changing right okay so Watch What Happens right because bold is specific to text and because we're

wrapping each view in a new view right well once I wrap it in you know dot frame right as my first modifier I can't put dot bold down here right I'll get an error command B it's because value type sum view has no member bold right like text has dot bold but the combined you know modified

content of text and frame does not have a bold so when you're using specific modifiers like that uh you need to put them first and again those are you know specific to you know this example like bold and text so that's an example of using you know the environment type modifiers and then specific modifiers now there's a ton of modifiers out there summer environments some aren't some are specific

some aren't I don't recommend going through the entire list and trying to memorize like what's what again I think as long as you remember what's going on every time we add a modifier we're wrapping that in a new view and you know as many times as needed and that the order of the modifiers matter if you remember those two key things uh you're you're well on your way

in this video we're going to talk about view Builders right and the main takeaway here is basically what they are so you know they exist and then the the limitations of them so you can set your expectations and not get frustrated like I did before I knew what they were okay so in our code here on the weather app let's use our z-stack for example and I'm gonna do

the code folding again on the v-stack just to make this clean and nice and easy to see here I'll blow it up so you can read it a little better so what the view Builder is is this closure it's not it's not a typical Swift closure right but you know the z-stack takes an open and closed curly brace our v-stack takes an open and close curly brace right all the all the elements that

return a view that is the view Builder right the open and close curly brace the scope of that is the view Builder and like I said they're limited you can't write any code you want in a view Builder you can only write you know certain things more on that in a second but if I Let's uh command click on v-stack do jump to definition get into some documentation here so we can show

you right so on the initializer of the v stack remember how we we showed it has an alignment parameter which you know has a default value of Dot Center for the horizontal alignment has a spacing parameter default value of nil that's why we didn't always have to use them but we could if we wanted because they had default values that's just a little extra repetition review

there but the last parameter of content you can see is marked view Builder right and it returns content if we scroll up to see what content is it's just it needs to conform to view so content being marked view Builder makes that closure that scope uh you know it's different special again like I said you can't write whatever code you want in there you know for Loops whatever well

at least for now because the uh functionality of these view Builders is expanding right it started off very basic in iOS 13 which is basically if else statements and I'll show you that in action in a second but in iOS 14 it got functionality for you know if let as well as switch statements

which is nice so the functionality is slowly expanding who knows how far it will expand but I do expect more functionality to be in these view Builders down the road okay so let's get out of the documentation into our code and again to review the view Builder is the scope of the open and close curly brace you know of the z-stack or of the v-stack now I'm going to

show you some of that logic in action in my Consulting project app all right so here we are at my category list screen let me put it up on the screen so you can see what you're looking at it's basically just a list of items that if we tap on it we can show a sheet of the

detail and then we can add to cart you know whatever so if we go back to the code let me break that down for you and I'll keep a little picture of the screen up there so you can kind of you know correlate what's going on so that list is basically a z stack as you see here at the bottom of the z-stack is our grocery item list and I've code folded all the implementation

because it's quite long that will be confusing I'll tell you what I'm doing just so you know so I'm showing the grocery list on up here is where I fire off to the view model to make the network call to actually download you know what's in that category uh the sheet is how I present you know when they tap on it it presents all the detail view that's what's going on there and then this

alert is for you know any errors in the Network hall or any errors whatever we pop up the alert so that's what's going on on the list super high level don't want to confuse you but the main point I want to show here is okay so it's in a z-stack so remember z-stack is vertical layers of views so

at the bottom of the v-stack is my my list well on top of it I'm conditionally showing either a loading view or an empty state right like I said I make a network call to to get all the items well while it's loading I put up just a blank white screen with a spinner right it's nothing crazy nothing special but that goes on top of the Z stack so that's all you see so what happens in

The View model when it's done loading uh that'll publish out to say hey I know loading equals false so now it'll redraw this View and now I'm kind of going into review on the whole you know view tree reloading and updating and now it'll go through this is loading will be false and then if my category list is not empty none of this will show right because it's in an if statement and

the only thing that will show is my grocery item list right but if you know it is loading now my loading view will show uh and if it's done loading but I have no items in my my list it will show the empty state that you see here so again this is using the if statement in the view Builders this is how you can conditionally show views in the viewbuilder you know depending on what's going

on like I said if everything's fine cool show the list if it's loading show the loading view if it's empty show the empty state right that's how I'm conditionally doing that and like I said new in iOS 14 you can now have switch statements in here if you have like five different view types you need to show based on some piece of data you can now have switch statements in here which is really

nice and then you can now have if let you know to handle any optionals so that's viewbuilders and again the key takeaways here are knowing that they exist and knowing what they are hopefully you know that now and then knowing the limitations of them that you can't just write whatever code you want in here you're pretty limited to basic control flow like if else switch statements that kind

of stuff so if you find yourself trying to write all the code you want in in your viewbuilder and it's not working this is why I know when I was first learning I had so many headaches because I didn't learn that and I was just trying to write whatever I wanted in here I learned it pretty quickly when nothing worked but hopefully I can save you that headache so that's view builders

now let's talk about how swift UI actually updates those views when the data change and before we dive into that too much we have to talk about how swift UI uses strucks for its views versus classes for its views like in UI kit so looking at UI kit for example like a UI button right you see that inherits from UI view inherits being the key word there because that means UI button

has all the features and functionalities of a UI view that they probably don't need all of that so there's a lot of bloat that gets inherited right it kind of makes the classes a little more heavier well in Swift UI a struct just conforms the view like there's no inheritance going on so in Swift UI The View structs are super lightweight and performant like I said they get created and

destroyed and re-rendered all the time in Swift UI and the reason that's possible is because they are super lightweight strucks so that's the key piece of information you need to know before we dive into the view trees and the diffing and all that stuff so I'm going to illustrate the view trees in two ways one in code and then one visually after we do in code just hopefully hopefully that

helps you make the connection so in our code here our weather app just our content view I don't know if you have these code folding ribbons on the side but if you go to xcode preferences text editing and then code folding ribbon make sure you check that box if you want to do what I'm doing if you just want to watch that's fine anyway so with these code folding ribbons do is I can

like fold up the code so I'm going to fold up my v-stack right remember the v-stack is what holds all of our elements so let's fold up that v-stack to illustrate this tree here so if you click that arrow that folds it up and the reason I want to do that is to show you like the base of our view tree

is our Z stack right and our Z stack has two elements it has our background view which is on the bottom of the z-stack and then it has our v-stack which is on the top right that holds all of our elements so that is kind of the the root of our tree right this Z stack you know off to the

left we can put our background off to the right we can put our v v stack and that v-stack would you know break down into more branches on that tree and those branches of the v-stack tree as you can see if I unfold it you know would be the city text view the main weather status view another hdac which again would have its own branches so you can see this this view tree can get a little

complex as you have a lot of you know branches I'm going to try to keep this as simple and high level as possible to not confuse you so you know if we were to fold up the H stack there you know that shows all the elements of the view stack and for the purpose of this explanation this is as deep

into the tree as I'm going to go again as to not overwhelm and confuse so that is it kind of in code and hopefully you can kind of see you know how the branches of the tree branch out if you can't I'm going to do it visually and hopefully that'll help so here in the high level visual I just cut out sections of the screen to to help you visualize it right I figured that might help

to see how this uh the view tree is structured and again to be clear in reality it's a bit more complicated than this because there's a lot more sub-branches but keeping it at a high level to explain the point right because the point of this video and where we're at in Swift UI fundamentals the point is not for you to understand all the complex stuff Swift ui's you know tree diffing

algorithm all that stuff like if you want to dive into that you know that comes later right that's not what you teach in the fundamentals course if you leave this video just understanding how the view tree Works how swift UI compares the view trees and then only updates the views that are necessary like that's great that's what you need to know at this stage of the game all

right so let's use this visual to explain what I just said about how swift UI only changes what's different so you see the view tree here well when an update happens there's an identical view tree that gets created this is why we have to declare all the rules of our UI up front is so the trees are exactly the same and that is for performance reasons to get a little Technical and look I'm not

gonna I'm not gonna [ __ ] you I'm not gonna act like I understand Swift ui's tree diffing algorithm I know the basics of what's going on so I'm going to explain that to you so the reason the trees are exactly the same is for performance reasons right if the trees were different now that algorithm would have a much much higher run time right however if the trees are exactly the

same the diffing algorithm between the two two view trees can be very very fast so again that is why we declare all the possibilities of our UI up front that way the view trees are the same for different algorithm purposes okay so what happens when we flip our is night from True to false or false to True vice versa when that Boolean changes with UI goes through the view tree to see what

changed and then when it gets to a view where that data affects it it triggers the body property of the view remember every view has that body and it will re-render and re-update that based on the new data so let's walk through our tree real quick to see how that would play out right so we start

at the top of the v-stack our is night change the true well we'll go down to the left here look at our background color okay that view is affected by is night being true so we'll trigger the body to re-render it's going to re-render it's going to show the right colors based on the is night Boolean good to go that view got redrawn then if we go down the other branch of the tree into our

v-stack we see we have the city name well that didn't change so that's not going to get redrawn then we go down to our v-stack that holds our our main weather status well that did get affected by the Boolean right we're going to show the moon and the stars not the cloud in the Sun so that View's body will get triggered re-rendered and show up differently on the screen and then down the

rest of the v-stack write our H stack of days that doesn't change our button doesn't change so none of that gets re-triggered so that is how swift UI only updates like what changed so even if all the structs and the views are getting destroyed and recreated the body's not firing off unless there's a difference so like I said this gets much more complex under the hood but at a high level what

you should know now the key takeaways are that there is a view tree structure The View trees have to be the same that's why we have to declare all the possibilities up front in our UI and then when the data change Swift UI will go down that view tree look to see what views are affected by that change and then re-render just those views so that's the big picture takeaway from

this section if you understand that you're good to go for a swift beginner I wanted to include this fun video just to share my story with swift UI how I was you know pretty taken aback when it was announced I was a little skeptical at first in you know my journey on learning it if you don't care about this stuff skip this video feel free but I wanted to share kind of my journey and

how I got to where I am right now with swift UI so in Swift UI was first announced at WWDC 2019 um I like it messed me up like I was shook as the as the kids say because it was a pretty big deal and like I knew it was a whole new way of thinking so I knew I was going to be like a beginner again

you know I knew this was like obviously Apple's direction for the future it was a pretty big deal and you know my career making content around this stuff like everything was going to change you know I had all these great wwc plans for 2019 I took the week off of work to cleared my calendar this happened and like I literally did nothing there was like so much to take in I was like

okay I I just sat back and watched videos I didn't put out any content even as all the other you know content creators were putting out all kinds of Swift UI stuff I didn't do anything and actually even as of today November of 2020 there's almost no Swift UI content on my channel now that's about the change because I wanted to wait until I got some experience with it learned it you know

Etc but yeah when it was when it was first announced I was pretty shook and uh it it messed me up it messed up my whole content plan had to like change everything because like I said this was obvious uh this was the future but when it was first announced I was a little skeptical like right I I tweeted this out partially because the developer reaction was oh

like almost unanimously like glowing everybody loved it and every time like a large group of people are just all in on something I kind of like take a little skeptical approach I'm like wait a minute and even during the presentation it like seemed too good to be true you know they were building table views in like two seconds and four lines of code and it just felt too good

to be true and one of my biggest skepticisms was like every app is going to kind of look the same and a year and a half later I think that's kind of playing out and the reason I thought that even from like the instant I saw it was you know to make a list you just type

list and there it is or a form and then you get all like the default form now I know in Swift UI you can customize and make it but you get all the stuff out of the box for free that I was like man a lot of the apps are going to look the same and I think you can really tell a swift UI app uh they

do they look a lot alike and now you could argue that's a good thing or a bad thing right it could be a good thing because now apps are going to be so easy to use because everybody's familiar with it right that's good usability ux however you know you're gonna lose a lot of the character of a lot

of apps a lot of the The Whimsy if you will so I can see the pros and cons of it I don't know where I fall uh you know like I said there's good and there's bad I guess we just got to live with that but when I first started learning like I I really struggled with swift UI because like I've said

you know in this course previously it's a it's a complete mindset shift and like all my old habits and ways of thinking like wouldn't work you know and I did I did the 100 days of Swift UI I did mang two's course there's a lot of other YouTube tutorials and it just it wasn't clicking like you do let me let me rephrase the building the UI like hdax V Stacks like that clicked almost right away

I hate saying things are easy because everybody's different but to me the UI aspect of Swift UI like getting it to look how you want is the easy part like that's relatively straightforward to me again sorry if it's too hard for you I apologize to me what was like hard to get click was like moving data around like I said this I don't know if I've said this in this course before maybe

um recording the videos kind of out of order but anyway it's very easy to get your app to look how you want it to me it was very hard to get my app to act how I wanted it right and that's the whole like passing data around and that's why I wanted to focus this course a lot on you know State binding State object observed object like making your app act like you want is what I

want you to leave this course like having a good feel for but for me when I was learning like that kicked my ass and to be fair to myself um like I was only like half learning right like I was still doing my other projects you know making my videos still living in the UI kit world and every once

in a while I would dabble in Swifty why so I never gave it like the full Focus until a few months ago when I got a Consulting project again brand new project as you can see on the screen here I'm showing some screenshots like the app is like dead simple UI wise right nothing complex is going on it's just table views you know nothing crazy right so it was a perfect candidate for

Swifty why not to mention the client was like very forward-looking he wanted a latest and greatest technology app because he's trying to build a team around this up and coming product and you know he wanted to attract you know Talent right because who wouldn't be interested in working on a Swifty app that's iOS 14 server side Swift right it's like a swift developer's dream if you're willing

to put up with the uh the headaches of being on that Cutting Edge so like I said I was like half learning before kind of doing it here and there but when kind of your full-time job gets shifted to working in Swift UI day in day out uh you start to pick it up pretty quickly right you're putting

a lot of time into it and this project is where I got comfortable with swift UI now don't get me wrong I had many nights of banging my head where I couldn't figure stuff out just Googling every little thing I'm not gonna act like I picked it up right away but we we got there eventually and this is where I got the hang of mvvm as well because again before this app I had dabbled in

it done a tutorial but I never built an app in it however this app was built in mbvm not originally I refactored it into mvvm but again that's how I got the hang of it if you've heard my content before you know I'm big on like repetition and practice well when you refactor eight screens back to back to back to back into mvvm that's a lot of repetition in practice so I feel like I got the

hang of it through building this app and now that I'm through that project I mean I'm still dabbling working on it with the client but for the most part I'm done there now I'm moving on to Creator view here's a sneak peek at a prototype but I am building my own product in Swift UI for the for the iPad the Mac all that stuff so I'm expanding my own knowledge and my horizons uh in Swift UI

now by no means do I declare myself a swift UI Pro right it's very hard to be that because it is so new right very few people have a lot of like production app experience there so again don't get it twisted I'm not here saying I know everything about Swifty why you listen to what I say I feel like I've been very honest about that up up front and and that is why this is a

fundamentals like straight down the middle course we're not doing anything crazy we're keeping it to the essentials and that is why because that's what I have actual experience in and I feel like I can teach now don't get me wrong I have plans over the coming years to continue building you know my own projects and stuff and continue sharing that knowledge in future courses but again this is the

fundamentals uh we're going to expand to the to the fun crazy stuff uh as we go so that's where I'm at with swift UI and again there's pros and cons to fully adopting Swift UI early when it's not fully baked yet right it's still being built of course when you do that you're going to deal with all kinds of headaches and frustrations like that's that just comes with the territory

of doing that however I like dealing with like the latest and greatest like I've always been an early adopter for everything in my life so like I'm fine dealing with those kind of like headaches if you will but I just enjoy dealing with like the latest and greatest stuff so hopefully that just continues and you know Swifty why will mature eventually and more developers will

adopt it and shift to that this is obviously where Apple's going for the future but uh I'm glad you're here now you're here early as well well it'll be fun to grow together with swift UI in this app I hope to build something fun and useful for you as you can see on the screen uh it's kind of a reference for Apple Frameworks you know you tap on a framework modal or they're

called sheets in Swift UI pops up with more information and you can tap learn more to pull up a safari view controller to really do a deep dive on all these different Apple Frameworks and as we build out this project we're going to slowly start to expand on our Swift UI skills as you can see from the design here obviously there's a grid we're going to learn about that we're going to put

that Grid in a scroll view so we're going to get some exposure to that there's a navigation view we're going to pass data to a whole new view the the modal slide up and Swift UI they're actually called sheets but you know modal sheet kind of the same thing of course we're going to refactor we're going to dip our toes into mvvm a little bit model view view model super basic on that

just to introduce you to the concept and in the last video is kind of a little bonus I'm going to show you how you can quickly convert this grid and modal slide up into a typical list in detail view with like a navigation controller what they're called navigation views but trying to relate this to UI kit terms right like a navigation controller with a detail view we can slide back we're going

to convert it to that pretty quickly to kind of show you the power of Swift UI so let's get into it we're going to create a new xcode project hopefully this isn't anything new to you by now let's go ahead and make this full screen here cool and then we're going to do IOS app nice and call this whatever you like I'm going to call this apple Frameworks interface 50i lifecycle

Swift UI app language Objective C right Swift next uh and then save it I'm gonna save mine in my desktop save it wherever you like cool here we are brand new Swift UI project I'm going to minimize my right pane here hit resume this is kind of my typical starting thing get my canvas to not look ridiculous get it off the iPad pod 7 we're gonna go to the iPad iPhone 12 Pro and

let's make it not ridiculously huge there we go okay great so the first thing we're going to do is start a little bit of our data model right this is all about Apple framework works so we want to have a framework object right that has the the icon the name the description the the URL to go to with Safari all that stuff so uh click on your Apple Frameworks folder here do command n

for a new folder or a new file uh we'll just do a swift file because this is just part of our model hit next I'm just going to call this frame work it's our object name create cool and then we're going to it's a struct called framework and pretty simple for right now but name is going to be a string and these are going to be constants because they're not changing we don't want these to be

dynamic or anything like that so let image name right this is how we you know know what what icon to show that's also a string URL string that is also going to be a string and then let description also a string right so those are the four properties we need right now to you know populate our app now I'm going to save you some time so you don't have to type out all this mock

data uh on this video you'll see a file attached in the teachable platform it's going to be called mock data.swift go ahead and download the file open it up and don't don't like drag the file

mock data.swift go ahead and download the file open it up and don't don't like drag the file into the project just open it up separately and copy and paste it into this file like I'm going to do here so I went and copied that from that file I'm gonna do a command V here and there you see mock data and what we have here on this mock data is just an array of Frameworks and you

can see I've created all these Frameworks right I gave it the the name of app Clips the image name Will import those images here in a second an URL string for how we open up our view controller and then the paragraph you know description for each one now that we have like our data set up let's bring in these images right you see image name app clip well again attach to the video as

a file in teachable you'll see a folder called framework icons or something similar to that you'll be able to figure it out but download that folder and then drag your images in like this so if I I go to my finder open up the folder you'll see all these so actually back in xcode we need to do our assets folder let's go back to finder and I'm going to hold shift drag all of these in here

to my assets folder and there you go you should see our framework icons and then the names again match up with what we have in our model so now that we have our images in here let's go to our content view well actually I'm just now seeing this when we built our framework it put it down here I hate when they're always down there I like to move them up there and then eventually you know

put them in their own folders for like views model all that stuff we'll get to that later so anyway we have our framework the data is ready to go we have our images the last thing I want to do for this setup is this content view now I do this a lot in my tutorials and previous courses everybody always tells me there's an easier way cool I'm going to do it my way still here's what

I always do right because I don't want this to be called content view I want this to be called framework grid view right for a proper name so I know you can you know rename it but I've just had a lot of issues in the past trying to just rename a file and then like my my file paths get messed up because the name is wrong and like I spent hours like trying to mess with

those bugs so I know you can do proper renaming but I do it this way just for peace of mind and like start a stopwatch watch how long this takes right here's what I do I delete the content view I move to trash cool Apple Frameworks command n new file Swift UI view next and then I do framework

grid view create and then again it puts it at the bottom so I drag it up cool done now that took 10 seconds and I have the peace of mind that like all that pathing issue is not going to be an issue it's a fresh clean slate so again if you choose to and of course I forgot something so maybe not

10 seconds maybe 12 seconds because you have to go to your uh your app uh file here instead of content view now it's got to be framework uh grid view like I said right because content view doesn't exist anymore so go command B okay so 10 12 seconds instead of 10 seconds whatever but the point is now I have peace of mind that I am working on a fresh slate I'm not going to deal

with any of those like pathing issues so anyway that's just my I'm scarred I guess from that so if you choose to do the renaming cool fine I do it that way so that's our initial project setup but I want to leave you with another challenge and I'll admit it's a little bit repetitive but that's kind

of the point so as you can see in the design right look what our grid is made up of right the icon and the name what kind of stock do you think that is right it's a v-stack right you got the image at the top name at the bottom so in this quick challenge before we move on to the next video try

to create that v-stack real quick right that has the image of the icon and the name now remember we're going to be in a small grid and some of the framework names are long so when you format the text of the v-stack think about that right maybe our font needs to be uh Dynamic it needs to adjust to our our grid view so it doesn't get truncated or go down to two lines so how do you

format that text view so that it you know shrinks if needed so that's something to keep in mind and that's the first building block of our grid which we're going to build together in the next video so if you want to take a stab at that now's your time we're going to jump right into it in the next one

we left off last video getting our project set up with our data and our images and I left you with the challenge of building the v-stack so hopefully that went smooth again with a lot of repetition it's from what we did before uh however we're going to build that right now because that is the first building block of our grid so let's get right to it and see how my code compares to yours

if you did that so of course we're going to want a v-stack right because we have the image at the top and the title underneath it so like I just said image and what is that image that's going to be name right remember when we were doing the weather app we did system name because that was SF symbol

well now we actually have images in our bundle so now we do image name and then the string we pass in I'll just do app clip there we go so there's our image obviously that's huge that's way bigger than we want and if you remember what I said you're going to do with your images almost always uh is dot resizable probably like 99.9 of the time and that makes it look even more ridiculous

but we need to do that so now we do a frame and we're going to give it a width and height of 90 by 90. and again that is just me dialing in those numbers figuring it out so if your numbers weren't

by 90. and again that is just me dialing in those numbers figuring it out so if your numbers weren't the same as mine like you didn't get it wrong like you just dialed it in differently than I did so now let's put our text in right so text in our framework name and we're kind of hard coding this uh you know we have the object of framework but we don't quite have that framework object on

our grid view yet so we'll we'll kind of inject the specific framework later we're hard coding values now just to get our UI set up and to be honest that's usually how I how I build the apps before I have all my data from like a network haul or something like that I fill it in with like mock data or dummy data just to make sure the structure is correct and then I can kind of like

inject the data as needed so just a little tidbit there so we'll call this app Clips right so there you go now that text uh it's kind of small kind of skinny again we want this kind of big bold chunky so let's do font now here's where we're going to mix it up a little bit from what we did last time

last time we weren't kind of supporting Dynamic type we were hard coding our font values so so if I do font now I'm just going to do dot title and you can see well I'm just going to do DOT first to show you the options so dot and now you see you know body call out caption caption two footnote headline large title subheading right these are different categories of like font sizes but this

will support Dynamic type right so if I just do title two now whatever the user has a setting for a dynamic type this will respect that um but you know it's still not bold like we want but we can put a font weight on top of that right so font weight and let's do semi bold right but again I'll

just do dot to show you right black bold heavy light medium regular so we're going to do semi bold there as you can see so that's the basic text but if you remember when I gave you the challenge I said some of these framework names are long and our grid squares are only so so big so we're going

to need the text to be able to shrink to fit the name if need be so there's a couple more modifiers we got to put on our text for that scaled to fit there you go and then now what we want to do is we want to give it a minimum dot minimum scale factor and we'll say 0.5 so what this does here is

this says hey you now have the ability to shrink if needed for the text but we only want you to shrink so much right we don't want you to shrink to like 10 and be unreadable now this number you could dial it in you know you could change it if need be but we'll say only go down to 50 and to

be honest with you that might even be like too small we'll say 60. but you you can see how you can dial that in right so the smallest this text is going to go if it's like a really long name is 60 of the original size so that handles our font scaling when our name is super long now something

different we're going to do in this app is we're going to refactor as we go rather than wait till everything's done to refactor and especially something like this v-stack here we know if you look at the detail view on the screen here like we're going to reuse that v-stack in another view so this is going to be reusable for sure so again I'm going to copy and I put the struct in here to

start we'll put it up here so struct and then I'll move it into its own view or file later we'll call this framework title View and this is going to be adjusted later on but for now we'll do let name equal or be a string that we pass in and then let image name also be a string that we're going to

pass in um remember how I was talking about how we're kind of hard coding this for now well once we get our framework array working that we have in our data we're actually just going to pass in a framework to this framework title View and it's going to do everything from there so but for now we're going to kind of hard code this so now I'm going to do a command V to paste that v stack

and instead of app clip we're going to have image name there and then for the text here we're just going to have uh name right So eventually that's going to be framework.name framework.image name

Etc okay what did I mess up I know what I messed up VAR body right every uh every view has this body that is of type some View and then open and closed cool yeah you can't just put the v stack in a struct you got to put the v stack in the body there we go so yeah that VAR body sum view

should be the first thing you always type when you're creating a new view there and I didn't conform this to two man typos everywhere we're leaving it in though just to show you that I'm not perfect developers aren't perfect everybody makes these kind of silly little mistakes um I'm probably making them more than usual right now just because you know anytime you're talking

and explaining and presenting on a video you know you're not kind of like in just your your code mode if you will but anyway here's our framework title view uh refactor it so let's use it up here now uh frame work title View and now this is going to take in a name and it will do app clips and

then an image name which is app dash clip so if I do a resume we should be good to go here cool everything is the same that's refactored out all right now for the main event of this video Let's Start building our grid now grids were introduced in iOS 14 so they're relatively new to Swift UI lazy V grids and Lazy H grids so let me break that down a little bit lazy just means

that the views get initialized as they're needed for example you know v-stacks and hdax also got a lazy version in iOS 14. so before your whole v-stack would populate like if you had 10 views in your v-stack and maybe your your each v stack was actually pretty tall on the screen like a for example Instagram right if you see Instagram you know the photo the caption that could all be one

v-stack but that one v-stack takes up the entire screen so if you had 10 of those in your v-stack and it wasn't lazy all 10 of those would load even though only one of them is showing up on the screen so that's why lazy got introduced in iOS 14 to make it so it only kind of generates the views

when they're needed so grids are lazy by default at the moment that's the only way you can make them and then as you can imagine a lazy V grid is what we're going to build as you can see on the screen here that is a grid that's going to scroll vertically okay so a key component of building a grid whether it's vertical or horizontal is you're going to need columns or rows right so columns

for for a vertical grid rows for a horizontal grid we're going to need columns because we're vertical so for that in our framework grid view here let's create a variable let's columns equal and it's cool no we got to give it a type here because we're not going to fill it just yet so that's going to be an array of grid items I'll explain that in a second and that's going to equal

an empty array for now we're going to fill that array with with grid items let's talk about a grid item so if I type grid item you know you can set your your columns to be you know 90 points wide you know that might make sense because our frame is 90 by 90. we're going to do it a different way

but the the big picture of the point to put it super simple you can basically give it a fixed width height you know set your fixed parameters or you can do what we're going to do and initialize a grid item with DOT flexible and we're not going to do a minimum maximum width you could do that if you want like it's flexible here's the minimum size it can be here's the maximum size it can be

we're just going to do flexible with no parameters so there is no min max and what flexible does is based on how many columns you have it's going to fill that screen let's create the beginnings of our lazy V grid and then we're going to come back to these columns to show you that in action so here in the body of our framework grid view right we have our framework title view that

we just built we want that to be part of our grid so down here we can type lazy V grid here and you can see you can have just like v-stacks right you can have columns alignment spacing more stuff or you can just have columns and content now here's a little tricky thing with swift UI and this is a little bit of an experience thing that you're going to learn over time is sometimes

the autocompletes can be more confusing than just typing it out the more simple way so watch when I do autocomplete on contents and column right like what is this so columns it is giving me the grid items of fixed 20 or like that's what we you know we kind of demonstrated up there so for columns I definitely want just our columns array that we created up here on line 12. that's

what I want to pass in but now this is what I'm talking about like start menu token and menu token I have no idea what that even means it gives me these text placeholders like it's it's just much easier to type the lazy V grid like this and again you'll learn this over time just lazy V grid kind of type it out yourself columns right I know I'm going to want my columns array

and then literally just an open and closed uh closure there and we're getting two preview because it looks like we have two different views in our body we have our lazy V grid and our framework title is separate but we want to move the framework title into the lazy V grid right so it looks no different and you want to know why it's because we only have one uh column

there's only one column in our array and if I you know I'm highlighting the lazy V grid here you can see the red frame you can see that one column is taking up the entire width of the screen Okay cool so let's add a comma here hit return and we're going to add another uh grid item with flexible so that'll give us two rows so return enter okay so now we have two rows hit resume and

you can see well we only have one framework title view here let's put in another uh let's actually let's go crazy right put in a bunch so here you go there's two columns because we did two grid items of flexible and again eventually our grid is going to take our array from our dummy data of our Frameworks but we're hard coding now just to play with the layout let

me to show you this so you can probably imagine what happens if we add a third grid item here in our columns right we're just adding more columns every time we do this hit resume there you go three columns just like that guess what happens when you do four resume four right you see where I'm going with this but now you can see our UI might be starting to break down a

little bit because we made our vertical stack for our framework 90 by 90 right so you can imagine if you wanted a lot of columns you would probably have to adjust that um let's do five just to show you know this kind of gets gets silly here again I'm just kind of illustrating this okay so that's super cramped but you also you can see our text shrinking that's why we put that minimum scale

factor on our text okay so let's get back to what we're actually going to do here delete two of those grid items uh we definitely want three of them here so three in our array hit resume there you go that looks more like what we're trying to build again when we have our real data in there and that's what we're going to do in the next video this video was just setting up the basic

structure of our grid in the next video we're going to work on getting it showing the Frameworks in our array and getting our grid looking like you see here on that design so exciting stuff let's go we left off last time getting the the general structure of our grid in place we discussed you know how grids work with the lazy V grid how you have to Define columns we got that in place now

let's put in like our real data that's called mock data you get it so uh rather than like hard coding uh all of these so let's actually uh we'll keep one because we're going to uh need that so anytime you want to kind of iterate through an array to populate a list a grid sometimes even a v stack

or an H stack uh what you're going to use in Swift UI is something called for each and like I said this will iterate through your array and create each view accordingly so when we initialize the four each here you can see it takes in data and content and here we use this initializer because this means our data doesn't have to have that data parameter name right so for our data again if we

go to our framework here right we can see we're going to have mock data dot Frameworks and that's going to be this array of all this this mock data that I gave you so back to this so we'll do frame work no no my bad mock data dot Frameworks there we go so now ID when Swift UI is iterating

through all this data each one has to be uniquely identifiable for Swift UI to know what to change like if you're adding or deleting objects so for right now backslash dot self right because this will basically take the object at a framework and hash it and give it its own kind of identifier let's let's dive into that real quick because that may have been very confusing but again back

to these kind of uh autocomplete things I like to do this and then just open and close braces afterwards and C can be get our get our framework uh in the for each right not separately so there you go now let's do it command B we should get an error and as you can see cannot convert value of type void to framework title view so what I forgot to put here is as it's iterating through

this and this is very similar to like a for Loop that you may be used to you need to like have a a name for each item well you could do underscore to not have a name but we want a name we want to do framework is what we're going to name each of our elements and then in right just again kind

of like you're iterating through this so now what that does for me is that as I'm iterating through instead of hard coding app Clips right I can do framework dot name again this is kind of similar uh you know to a for Loop that you may be used to in UI kit so framework dot image name right so that's what I'm doing I'm using this framework to to get the values I need from each framework

as we iterate through that now it's not it's not working because I'm missing a very key Point here it says generic struct for each required is that framework conform to hashable okay so let's go to our framework object and the reason it needs to Hash the object is because like I said it needs to give it like a unique identifier and we're saying just hey the ID should just be self now

doing something like self is is fine when you have like maybe an array of integers but when you have a custom object like we do in our framework it's best to we have to conform to a hashable like this and then you're going to get automatic hashable conformance because when you use you know the fun the foundation types here like string and double because those are all automatically conform to

hashable if you have more custom types in here you might have to write your own hashable conformance but what I want to do to make this like super uh clear here and this is what you should do when you have custom objects like our framework is also conform to identifiable now you're going to see here command B uh type framework does not conform to protocol identifiable all it needs to

conform to identfile is an ID so I can click this hit hit protocol stubs we're not going to do the object identifier I guess this is kind of the same thing this is what I always do VAR ID equals just to initialize a new uuid and we'll actually make this a let because we're not changing it here make it a constant so here we gave framework an ID and it's going to initialize a new uuid

every time and that's going to be the unique identifier for this object when it's in like you know for loops and such so now back to our grid View now instead of ID being keypath.self

it's going to be keypath.id and what that ID is again back to framework the property ID so that's how the four the four each is going to identify the object now the nice thing about Swift UI if we want to clean this up a little more is when you conform to identifiable like we just did uh yeah you can keep this here this ID but Swift UI is already going to know because this object

conforms identifiable I'm going to identify that object by its ID so this code is kind of redundant so if you want to clean up your code a little bit conform your objects to identifiable and then now you can delete that and Swift UI is going to know to look for the ID that way your for each is a little bit cleaner right for each our array of Frameworks and then the variable name

for each framework as it iterates through so now by by running this I should see like 16 app clips no what am I missing let's try it again sometimes previews there we go again previews can be a little finicky like I just said but um I said 16 app Clips but that's a lie because I forgot we actually passed in the framework.name framework.image name so you can see our grid is

uh let's click off here so all those red squares aren't cluttering everything up our grid is kind of taking shape it's not exactly how we want it of course but you're starting to see this come together but now that we have this framework here like I like I mentioned before let's take the time to clean up our framework title view so if we go down to framework title view here

right we don't want to pass in an image name and a name separately right it's all part of the same framework so we can pass in here is say let framework of type framework right so that's all we're going to pass in and then now we got to change our names here right so we got to do

framework dot image name and framework.name do command B to make sure everything is copacetic build failed what do we do oh yeah we haven't fixed this yet so yeah now our framework title view just takes in a framework like we've kind of done this before here so now uh we can do framework and then we're going to pass in this framework again as it's iterating through the

four each that's iterating through our array we're going to pass in each framework into the framework title view to populate that so again now our grid is actually very clean right we pass in our columns cool our four each again like I said the array each framework build a framework title view with the framework pretty straightforward so if I pull up the design real quick you're going

to see it doesn't quite look like what we have well one it's not in dark mode like what do we psychopath let's go back to our preview here if you click this icon here we can change the um you know what our what our preview looks like right if you want to change the device the layout we're going to change the color scheme right and also below this you can check Dynamic type right

if you want to test what your app looks like so this little environment overrides is a great place to test your app on the fly in the preview we're going to keep it simple just now change it to dark mode because we're not Psychopaths and you see what it did to our preview here right here's our preview struct well we used to have just framework grid view but now we we added a preferred color

scheme dot dark so if you wanted to convert the dark mode just by typing that line of code you can or you can go to the environment overrides and change stuff here right so now we're testing this in dark mode now let's add our navigation view to get our nice looking Apple Frameworks navigation title okay so here in our body which again is is only a couple lines of code again the

goal isn't to get to the minimum lines of code it's for maximum understanding like I'm going to kind of pound that into your head but I feel like even though this is only a couple lines of code very understandable at least in my opinion of course that is very subjective I get that okay so let's wrap this whole thing in a navigation view right so the navigation view if you're coming from

UI kit which I think a lot of you are is basically a navigation controller right so that's all we did to add a navigation controller right and if you remember how navigation controllers work they they hold uh an array of view controllers I'm speaking UI kit terms right now right the navigation controller itself doesn't have a specific title like the Apple Frameworks that you

see in the design right as you're swiping through a navigation controller that navigation title is going to change based on what screen is showing so this threw me off at first right so when I want to add this navigation title in Swift UI back to our code I thought hey here's my navigation view cool let me add navigation title and we'll do you know I like to add the Emojis here Apple

uh Frameworks so when I wanted to add the navigation title I tried to add it to my navigation view thinking that makes sense right that's logical but again if you think about that UI kit example I gave you it's the content in the navigation view that has to know what title to show so that's why you put the navigation title on the we're going to put it on our grid

here eventually we'll put it on something else but right now our grid is the top level view in our navigation view as you can see so um that's not the desired outcome obviously or is it I don't know what's your style who knows so we need to put our lazy V Grid in a scroll view now if you've ever built a scroll view in storyboard or programmatic was a little easier than storyboard

but building a scroll game storyboard is a nightmare uh watch how easy it is in Swift UI I'm going to type scroll view open and close braces and then we're going to copy or cut the grid put it into the scroll View and by doing that we're leaving our navigation title on the scroll view real quick tip if you want to see what is on something this was introduced a couple of xcode

versions ago but using your arrow keys just Arrow left and right over a brace and it'll show like what you can see this flashing yellow light that means that brace is the scroll View and if I go to this curly brace oh that's my v-grid like up to this one okay cool that's my for each because sometimes Swift UI curly braces can get out of control so that's a nice way to see like what's

what so that way you can tell our navigation title is on Frameworks we put our lazy V Grid in a scroll view which all of that is inside our navigation view hope that made sense but now when I run this here on the preview now we get the the scrolling action that we expect and you can see the navigation title you see it went up smaller at the top we get that nice blurry effect up there

with all of our Frameworks so just like that and only a few lines of code one last little tweak and this is just personal preference but I feel like our Frameworks are pretty cramped right it's cramped up at the top here it's cramped uh all the way look like look at SF symbols it's cramped all the way here to the left of the screen so what we can do here is in our framework title view right

so each individual framework is going to get this padding right so on the v-stack of our framework title view let's add dot padding and if you see what that did that just space things out gave it more room to breathe in my opinion that's that's a nice cleaner look this is totally subjective though here real quick watch watch the preview I'm just going to comment out the code real quick uh

this is with padding that's without padding with padding without padding but it's cool how you can play around with like looks like that in Swift UI literally in like seconds so let's put the padding back in there because I like that um so our grid is built nicely and then again the cool thing is like here's the code for our grid you know and again I try not to brag about look how little

lines of code it is but this is a case where it's nice nice and readable easy to understand what's going on now the challenge I'm going to leave you with at the end of this video is to try to build our detail view a whole separate screen as you can see in the designs right we tap on a framework and the detail view slides up now I'm not asking you to pass the data connect everything

no we're going to do all that in a future video all I want to see if you can do is to just build the UI structure of the screen and I'll give you a hint it's just a v-stack so nothing all these challenges I'm not trying to be like too crazy if you haven't noticed that yet again I want to get you practicing building these skills but in the next video we're going to build that screen

together but if you want to take a shot at it on your own go for it alright see you in a bit we left off last video getting our grid in place as you see here I left you with the challenge to build the UI of the detail View and that's what we're going to do in this video so if you struggle with that challenge don't worry we're still early we're still getting started we

got plenty of practice to go if you did complete the challenge now's where we can kind of compare code and compare methods and you know see how it went okay so the first thing we're going to do is going to be a separate file so click on our Apple Frameworks folder command n new file new Swift UI file hit next we're going to call this framework detail View create cool it's blank let's get our

uh preview up and running nicely there we go hello world cool so again pulling up the design uh let's talk about the overall structure right so we have our uh framework title view like the v-stack we've already created right remember we said we were going to reuse that so that's one part of the v-stack and then we have our body of the description right the two paragraphs or

one paragraph whatever that's another part of the v-stack and then we have the button at the bottom that's the final piece of the puzzle if you've seen the upper right we have a the X dismiss button more on that later but that is also going to be part of the v-stack so I like to take this

step by step I mean I just kind of broke it down for you so what we'll leave the X towards the end because there's more explanation there for why we're doing that but let's start with our framework title view right the reasonable v-stack we created so here in our body uh let's get rid of the text here give us our kind of overall v stack and let's create our framework uh title View

and here's what's where it gets tricky right so it takes in a framework well okay we don't we haven't passed in the framework yet we're going to pass data in the next video uh so but I can set that up right so I can do VAR framework that we're going to get uh and it is a framework now

when you create a variable uh on your your view overall but you don't give it a value like and you want your preview to work you're gonna have to give your preview of value like it's got to know what to show right so you can see missing argument for parameter framework and call hit that uh fix it cool so now it's expecting a framework well if I initialize a framework you see it takes a name

image cool so I can initialize one right here well we'll go to our framework real quick I'm just going to give you an example here so I could could copy paste this go to our framework detail view let's move that up if I wanted to just kind of paste that framework initialization right here ah like this will work if I hit my preview well editor and Source um gotta pass in framework up

there so it knows what to do now try again on my preview there we go app clip so this works but man this is sloppy even if I like made my canvas small like I don't I don't want all that in here and oftentimes when when building a preview you'll find out that you have to pass in a lot of

your objects and then if you're passing in object you have to like initialize a new one and some of those initializers can be long like as you can see here so that's like super sloppy so this is why I like building nice mock data so if we go to our framework model here just like we had our array of Frameworks we can do something very similar static let sample framework right so just one and that is

going to equal and we'll just let's use you can pick whatever one you want we'll use AR kit right who doesn't like who doesn't like some good old AR so copy AR kit and now our sample frame framework equals AR kit so you know our our messiness right if you will or kind of the necessary evil of having all this stuff is in our mock data file right kind of separate away from our nice

neat code that we want people to use and read so now instead of initializing this here right I can just do what framework do I want to pass in I want to pass in mock data dot sample framework is that what I called it yeah how quickly you forget so if I do command B now try again on my uh simulator or

preview come on preview work with me here there we go um so now AR kit is showing up and our preview is nice and clean right mock data that sample framework so that was a little aside but as you build more and more complex apps and you want the preview and I'm going to be honest sometimes my My

Views will get kind of complex that I just give up on the preview I'm like you know what this View's just not gonna have a preview because it's I don't want to take the time to build it maybe that's bad practice but I'm just being honest that's how I kind of worked in my last app sometimes I didn't take the time to build the preview uh because it can't get complex so anyway that is the initial

step of our detailed view now what's the next step of the v-stack like I said well it's our our body our description well that's just the text here so if I do text and what's the text we want to pass in we want to pass in framework dot description right so bam there you go it shows up right away

now we want to adjust this text a little bit right because as you can see it's it's hugged up right up against the edge right you want to make this because these are going to be paragraphs in you know I tried not to make them walls of text right you don't have walls of text in your app uh so I

tried to break them up a little bit but I want to make this easy to read so let's get it away from the edges here how do you think we're going to do that we're going to put padding on it so dot padding there we go now it's spaced out nicely as you can see that's that's much more easier on

the eye one thing we want to change as well is the font now remember like I said this is not a title as you can see title is huge you don't want it to be like that we want body so body is more just for like actual reading like paragraphs like we're doing here so there you go uh there's the body all

right so we got that in place now the next piece of the puzzle is the button at the bottom so we've done this before in our weather app button again the first part is the action the second part is the label what it actually looks like and we're gonna do the same thing we did in the weather app

so text and the text is going to be learn more and again as you can see we just get the learn more blue button that's pretty basic we want to make it actually look like a button so let's do fonts again this is a little bit different last time we hard coded a font of 20. uh this time we're going to support the dynamic type dot title two right so that's getting a little bigger again

I want to make it semi-bold dot font weight dot semi bold right not too bold but bold enough um so again that's one button you could do uh but we want to again put the background around it so dot background color we do color dot red but red and blue doesn't look good right so we want our foreground color which is going to be our text color dot foreground color to be dot

white there we go well that looks pretty cramped of course right because we didn't give it a frame and now here's an example of where the order of the modifiers matter right so you may just be like okay cool let me give it a frame frame and then like I mentioned you know my typical go to button is 280 by 50 that's just my personal preference change it if you like cool but you may be like

wait a minute wait it doesn't look any different well again that's because we're putting the frame on after we've already established our background color so the frame's got to come before background color so the background color actually fills up the frame right so there you go now you see the change here down in the lower right and then the final touch that we're missing is that corner

radius of 10 right just to round off those Corners a little bit to get the button looking nice uh so that is our button here in the v stack now the button is kind of cramped up against the text right I want the button to be pushed down to the bottom so if I want the button to always

be pushed down to the bottom what do I need use a spacer so we'll put a spacer above the button spacer there you go and as you can see that pushes the the button to the bottom but again as you see we put the spacer in this area here so it's going to push everything above it as far as it can go up

to the top well we don't want that so let's put a spacer above our AR kit v-stack right or our framework title view so we'll put a spacer here to push that down and now it'll like even things out right the spacers these two spacers will do their job to have an even space at the top and an even

space at the bottom and push and push our content in the middle and that's kind of the look we're going for okay and as I said before we're going to refactor on the fly as we go right so this button here again you're going to most likely use buttons all throughout your app so let's do command C to copy and over in your Apple Frameworks command n create a new file Swift UI view we'll call this

AF for Apple Frameworks uh button so AF button create here we go now in our body because I copied in that text earlier just paste that text let's get our preview going and so you can see we have a preview of our button if you want to like tweak it maybe adjust the design a little bit you have

this nice isolated preview we don't want it to be learn more all the time we want to be able to pass in uh of our title string I want to be able to pass that in and then put title into the text all right so now our button can can say whatever I want it is in this case you know remember last

time well hold on let's update our preview remember like I said if you if you have uh properties on your view you have to pass them in the preview so we'll say test title just to show that it is going to update the preview here so it went from learn more to test title now last time we actually uh kind of made colors and foreground color the property to make it like super flexible

well let's say we have a certain style in our app it's always going to be red our our font is always going to be white so that way all we got to pass in is the title so let's go back to framework detail view instead of having all this code we can just do AF button and then pass in a title

of learn more and again our code and our view is nice and clean I personally like to have spaces in between each like element to me that helps me visually like realize what's separate and what's not that's a personal preference another personal preference dark mode this I just don't like the way this app looks in like light mode anyway I think it looks so much better like that

now the last piece of the puzzle here is when we present the screen modally as you see in the design it's going to pull up the card right you see how it takes up like 98 of the screen you may have seen this in like your day-to-day apps well when it does this you can just swipe it down and you don't have to write any code for that you get that functionality like automatically

something you should know about when you display something modally which is quite common in apps is the human interface guidelines by Apple let's go to that real quick here so and I'll link to this in the description of the video so the human interface guidelines on modality right presenting a modal here's the example they showed like the the mail app right you slide that up well if we

go here right so yes you get that swipe to delete for free you may think uh that's enough but here in the human interface guidelines here's why you should always include a button right well because they say always include a button that dismisses the modal view I'll make this bigger so you know I could be sure you can read it on the screen right for example you might use a done or cancel we're

going to use a little X including a button ensures that the modal view is accessible to assistive Technologies and provides an alternate alternative to dismissal gestures so human interface guidelines basically says always add a button to your modals don't rely on just the swipe so we're going to be good citizens Iowa citizens here and we're going to adhere to that so we want

to put our X in the upper right hand corner okay so let's start doing that so we'll put it at the very top we'll do a button uh very very similar to what we did with the AF button down below label and what do we want our label to be what do we want it to look like well SF symbols has a

generic X right we're going to use that so that's going to be an image of system name right not just name because we're using SS symbols called x mark right so there you see there's our blue X pretty small it's in the middle it doesn't look like how we want it so let's start changing that let's give it a foreground color dot foreground color now you could dot white you may think that but dot white

is going to be dot white on the black background and Dot white on the white background so you got to support light and dark mode so you can't just do white right so you can get access to UI kits um you know System colors right that adopt to uh light mode dark mode so you do color and you initialize the color with DOT label right and this is this whole dot

thing right this is where you get all the again System colors from UI kit right Dot right where you can get like you know system fill secondary system placeholder text right so label is one of those that will be essentially black uh in light mode and white and dark mode is what that label does so that X is quite small let's make it a little bigger you can do image

scale and you can see dot medium small medium large we're going to do that large and this is something you can do with your SF symbols I tend to do that a lot and then we'll give it a frame of 44 by 44 because that's a typical touch Target right you don't want your touch targets to be so

small that they're hard to press right and you'll see when I run this uh you'll see the touch Target I get like you can see it clicking you can see it like fading out well you can see I can click over here and still get it and if I'm clicking here I'm not getting it right so we made our touch

Target pretty big right so you can you can miss the X and still hit it now the the final piece here is okay it's dead center um maybe maybe we're doing a new design style I don't know but we probably want it over off to the right that's pretty typical where dismiss buttons are so how do I move my x button over to the right well v-stack has an alignment I can do

the alignment um parameter on the v stack here and I can do dot trailing okay well that moves everything to the right so I'm kind of showing you what the v-stack alignment can do that's not what we want and just you know you could dot leading about leading cool uh okay that's not it so okay we're going to leave the alignment as is on that v-stack however what I could do is I can put our x

button which is right here I'm going to refactor this out in a second into an H stack so H stack and let's put our button here into that H stack command X command V so now our button is in the hdac but you'll notice uh nothing changed well what can we do to push it to the right in an

hdac a spacer right so if we put a spacer in front of that button uh now it's going to push that X all the way over to the right too much to the right in fact let's add some padding onto our overall H stack to give it more space more room to breathe not so much right up to the edge so here we have this hdac which again goes across the top pushes the X to

the right and we keep all of our content pushed towards the bottom uh where we want it right we want it to be at the bottom of the card above the button that wraps up the UI for our detail view we're going to come back and refactor that X dismiss button later because we still got more to do with that and in the next video we're going to pass data and connect these screens

we left off last video building the UI for our details screen that you see uh here in my preview well in this video we're going to work on connecting everything so that when you tap on a framework this detail view will slide up and you can dismiss it so let's talk about how we're going to do that first if we go back to our grid view right that has our grid here and you can

see our for each right remember this for each is what's building each individual framework title view well you know in UI kit in like a collection view you know you would have like did select item at index path right that may sound familiar to you we don't really have that in Swift UI so we actually put a tap gesture on the individual title view right so we're going to do that now and

then we're going to explain like how we manage the data and like how we actually do this so I just want to add this real quick so on tap gesture right and then you see the closure with the code again I just you know I just like to have the on top gesture with just the code pretty simple uh

and here's what we want right now I'm just gonna put print you know whatever just to get xcode to not yell at me so I'm going to kind of relate this to UI kit in order to explain Swift UI and I want to explain it that way so I can you know reiterate the imperative way of thinking versus the declarative way of thinking right part of that mindset shift well in UI kit you can imagine

on this tap gesture or again it was was you know did select item at index whatever uh you would say Okay present the modal screen with that framework like you would specifically say that in your did select delegate method again in UI kit right but that's the imperative way you're telling the UI exactly when and how to update whereas remember in declarative we just update the data right we

update that source of Truth and then our UI reacts to that change and updates accordingly so again that's the major shift so what we want to do on tap gesture here is we want to update our source of Truth or our data and what we need to update is what framework we actually selected now here's what we're going to introduce nvvm or model view view model and real quick this is

going to be a dead simple implementation super basic as we've been doing throughout the course we're going to build on that in future apps but this is kind of like your introduction now before I give the overview of what mvvm is let me give the typical architecture debate disclaimer right no matter what you're doing what architecture to use is always going to be some sort of debate

in the developer Community right if we're coming from UI kit or it's MVC mvvm Viper MVP it seemed like there was a hot new architecture like every couple months right and that's that was one of the most common questions I always got asked is like what architecture should I use so when it comes to Swift UI it seems like the early consensus is mvvm you know but I've seen plenty of dissenting

opinions on Twitter saying that mvvm isn't the right architecture so I guess what I'm trying to say is I don't think that architecture debate's gonna go away you're going to constantly hear other people recommending different architectures and that's just me giving the disclaimer like yes we're going to learn mvvm but uh you know there are going to be plenty of other architectures

that debate is going to rage on but again the early consensus seems to be mvvm but like I said in the beginning Swift UI is so early it's constantly evolving like there's a chance we could look back in three years and be like hey remember when we built Swift UI apps and mvvm huh that was funny or it could become the standard the point is the only thing I can promise you

is that things are going to change so hopefully through this course I can help you build those fundamental skills so that you can evolve and grow with those changes okay so disclaimer out of the way what is mvvm model view view model well let's start with the the end points right we have our model on one side which in our case in our app is our framework right our framework object and then

we have our view on the other side which you know in this early case is like our grid so to put it really simply and again this is the intro we're going to build on this more as we practice it and learn it but to put it really simply you have your your model which is all the data you have

your view which just displays everything and then the view model is a layer in between that kind of handles all the the display logic you know again keeping it big picture you kind of want your view that displays whatever it displays to be as you know dumb as possible right it shouldn't know about anything other than tell me what the display and I'll display it right there should be no logic

uh in your in your view that all should go in in the view model in this you know philosophy now do you need a view model for every single view you have no The View model should really only come into play when the view is is dynamic like things can change like in our example the selected framework is kind of dynamic right you can't like hard code that however if all we were doing was

displaying this list of uh Frameworks in a grid like you couldn't tap anything it was just display you don't need a v-model for that right you just read directly from the data or the model so you only need a view model when there's some logic and changes going on which to be honest with you is probably going to be most screens but I want to be sure to say that a view model is not required for

every screen if you're just reading and displaying data that's it so that's the high level overview again we're going to get plenty of practice with this in the coming apps this is your introduction so let's build our view model again it'll be very simple so click our Apple Frameworks folder do command n for a new file just a swift file because it's not a swift UI View and we'll call this

framework grid view model I basically use the name of the view and then like add model to the end of it right so hit create in import Foundation it's fine we're actually gonna have to import Swift UI and you'll notice everything in Swift UI has been a struct so far right well now we actually want to hold state so this is going to be a a class so you do class and again we'll call this framework

grid view model and then the key to make this uh the view model for your Swift UI is to make this an observable object so what this allows is for our object to publish information right kind of like broadcast like hey I changed and we need to make sure we set up the proper views listening to this so they can update their views when their properties change you're going to see

this in action if that was confusing apologies but you're going to see this in action uh one quick thing this should be a final class just that's just the general Swift note if you're not going to subclass your class you know make it final so what do we need in our framework grid viewmodel we need a selected framework right that's really what we're trying to keep track

of here so we'll do VAR selected frame work and that is of type framework and it's going to be an optional because at the start like we don't have a selected framework maybe if you wanted to give it a default value sure we're going to keep it optional so we've created the beginnings of our view model again it's an observable object so now we need to tie this to our framework grid

view so let's go back to our framework grid view well first I'm going to drag this up above I'm going to do project organization at the end so this will become less cluttered but framework grid view so now we need to use our view model here so I want to do at State object we're going to explain this state object so State object and observed object are similar I'm going to explain

the differences here in a bit VAR view model So This Is Us creating our viewmodel and it equals framework grid view model right and we're going to initialize a new one and we'll come back to this in a second but that's the difference between State object and observed object like when you're initializing a brand new view model like we are here you want to use State object if

you're are injecting it from like a previous View like when you initialize your framework grid view you initialize it with a view model then you're going to use observed object I don't want to get two in the Weeds on that right now because we're just introducing the topic but we'll we'll dive into that later so let me stay on state object for a second here what this allows let me hit resume

because that's bothering me what this allows is what okay whatever what the previews am I right um this is very similar to State remember how I said state is kind of like a little piece of data that persists while the view gets destroyed and recreated all the time right so you can imagine if this wasn't a state object right if our framework grid view gets destroyed we

rendered destroyed re-rendered which happens all the time like anytime you make a change then this is going to get re-initialized and every time it gets re-rendered because we are creating a new view model it's going to create a new view model and it's not going to hold state right because it'll initialize with whatever default values we gave it for example the default values

right now is our selected framework is no right so if we had a selected framework and then it got destroyed and re-rendered that would revert back to nil so that's why we want to hold State object because it's very similar to at States on our other variables where framework grid view can get destroyed and recreated all the time but this is going to be held off elsewhere and persist and

maintenance data it's going to stay alive while Frameworks grid view gets destroyed and recreated all the time I know I repeated myself a lot there but State object observed object this whole passing data this is one of the trickier parts of Swift UI and getting things to work correctly and this is just your first exposure to it like I said we're going to keep building

on this and use it a lot so for now we're going to use State object with our view model to create that now what we can do here is on tap gesture we can do View model dot selected framework equals framework and what we did here is this framework remember that we're passing into each framework title view when we tap it we're tap making our selected framework in our view model equal to that

framework so we know what to pass to the detail view so okay we're changing our source of truth right that's the whole idea behind declarative change the source of truth and the UI updates well now we have to set up our UI so that it updates so let's go back to our view model here and we want to create a variable called is showing detail view it's going to equal false by default it's a

Boolean now this property needs to be published right because we want our grid view to be listening for when is showing detail view changes because when is showing detail view changes to true that's when we're going to show our detail view right so our grid view back here needs to be like listening for that and waiting but in order to be able to hear it it's got to publish itself

so in order to do that you just add at published in front of the variable so now our view model whenever is showing detail view changes it's going to publish change and our grid view we haven't set it up yet is going to listen for that and change when it updates so now while we're in our view

model let's make some space here how do we get this to trigger well we can put a did set here did set and we can do is showing detail view equals true let's do a command B to make sure everything's good now what we're doing here is anytime the selected framework changes we're going

to make is showing detail view true right so when does selected framework change when we tap on the grid this will change this will flip this easy detail to true and then we'll show our detailed view so back in our grid view now we need to set up the detail view to show when that changes and our detail view is called a sheet so on our scroll view we can do it below our navigation title we

want to do dot sheet and we're going to do there's a couple different ways to implement these but we want to do is presented so is presented takes in a Boolean like is it presented true or false so we want this Boolean to be whatever in our view model is showing detail view is right whatever you're showing detail view is that's what we want right because that's what we're listening to so

back in our grid view is presented and we need to make it binding so dollar sign viewmodel dot is showing detail View and I'm going to get rid of this content parameter label because I don't need it put that there okay so what we're saying here is show this sheet whenever it's showing detail view changes now what view do we we want to show well we want to show our framework detail View

now if we initialize our framework detail view you see it takes a framework what framework do we want to pass in we want to pass in view model dot selected framework there we go now we have our detail view let's do a command B looks like I'm getting some errors here probably forgot something silly yeah it looks like I left this parentheses here from the the autocomplete and

I believe I'm going to get yelled at because this is an optional and I'm not unwrapping it yes that's what it is so what we can do here is a couple things we can force unwrap that's the easy route but that's a little dangerous what you could do is you could do no coalescing and we're not gonna we're gonna give it a a we're going to do mock data dot sample framework just to give it

a default value if that is nil now that's going to show app Clips right because that's our AR kit that's our sample thing what you would do in like a real app a real product is maybe you would have a detailed view like this that is meant for like the empty State and you know instead of saying AR

kit you could say oops could not find instead of the icon you could have like a sad face and then your body could say something different you could pop up an error message there's so many different ways to handle the errors for now we're just going to give it a default sample framework but that should be set up now to work if I hit resume on my preview our previous been acting up

hopefully it's good okay we'll hit play okay so now we're actually running it so now when I tap on a framework we should see the slide up card tap slides up I thought I was in dark mode well I can't dismiss it that's that's by Design I knew that was going to happen we're going to implement

that here in a second but let me stop this aren't we in dark mode yeah okay so this could just be a preview thing I'm confused right now sometimes previews act weird I'm going to run this in the simulator to make sure we didn't mess something up I think that's just a preview issue so here we are in the simulator if you do command shift a that'll shift the dark mode real quick okay so

we're in dark mode Let's tap on cloud kit okay so yeah that was just a preview issue again just showing you previews can be finicky they can be a little weird always test in a simulator or on a device if you see something weird going on in your preview don't bang your head thinking you have a bug if your previews are messed up double check it on a simulator or device so okay so this

is the expected Behavior I can't dismiss it I mean I can swipe down remember I said you got that for free you got the swipe down for free but we need to be able to dismiss from this button so we have to use that is showing detail view we have to pass that down to our our detail view in a binding so

it has access to it so when I tap the x button I can flip is showing detail to false and then it will dismiss so let's do that okay we'll stop running this uh back to xcode resuming the preview so like I said we need to pass to our detail view a binding of ISS showing uh details so in

framework detail view let's go ahead and give it another at binding VAR is showing uh detail View and that is a boo and what we're going to do here you notice in our button right here we're in our hdac with our x button right remember that we didn't give it an action before so it does nothing

as you saw now we want to do is showing detail view equals true and remember binding right I know I'm repeating myself but I want to drill these this passing data home binding makes is showing detail of you equal to whatever it is in the parent view which is our grid View and if you look in our grid view we're using the view models is showing detail view right this is what we need to

flip to show and hide the sheet so you'll notice if I do a command B what I need to do is update my initializer here for our framework detail view because before it was just taking a framework but now I need to have an is showing detail view by binding right so let's make our parameters uh like that I'm gonna okay just for sake of making this readable I don't know this annoys the crap

out of me when they wrap on two lines I've already explained to you how not the force unwrap it I'm going to go back to the force unwrap just so it's easy to read and looks nice for you in the video um again Don't Force unwrap it but just for ease of understanding and ease of seeing it I'm gonna

Force unwrap it uh so and now in The Binding we need to pass in dollar sign view model it's going to happen here too is showing detail view part of it is my font is ridiculously huge I guess I'll have to live with that um now you know why my code is nice and clean and readable because stuff like

that drives me nuts uh okay so what we're doing here is passing the binding like I said from The View model into our detail view so now when we flip that back in our detail view everything's gonna you know trigger and we're going to hide the sheet so let's run this on the simulator again just to be safe build failed I forgot something all right what's the what's the error here what

I forget missing parameter okay the previews I remember I told you previews can be a headache like we just didn't update our preview here with our new is showing detail uh on our on our detail screen right so right we added our issuing detail view to the initializer well you gotta update your previews as well now when you do bindings right because you're not really passing anything into

the preview you can do doc constant uh we'll say false this is just the way kind of like hard code bindings for your previews if you want to do that so now if I run on the simulator we should be good I'm gonna go back to the grid view here okay back to the simulator okay so now when I tap

on step on health kit I can swipe down that was good tap on health kit again now when I hit the X all right what what do we mess up so stop running this and take a look okay I found my issue embarrassing but we leave this in because this this type of little stuff happens right so I literally spent like three minutes debugging making sure everything I had

connected was working and I was like the binding's fine like this is this should be working what's going on again these are these silly mistakes that all programmers make well when I'm tapping my x button right it's showing detail view I'm setting it to true so of course the detail view is going to still show when I'm tapping X I'm setting it to true I need to be setting this to false so again

super silly mistakes can kind of lead to you know you debugging for a few minutes the wrong thing so hey happens to the best of us but we switch that to false now let's run it on the simulator and now you know let's go to catalyst so now when I hit X again now we're flipping it to false so

now it goes away four little characters messed me up for a few minutes there but uh our data is all being passed around working correctly you got the intro to mvvm let's go to our view model just to kind of rehash it a little bit uh so like I said it is a class and you want to conform to observable objects this way it can broadcast its changes the stuff you want to broadcast you put a

published in front of it so now anytime is showing detail view changes hit broadcast it publishes and then here in our grid view here in our sheet right our sheet is listening to that view model is showing detail view so whenever that changes our sheet shows in dismisses accordingly as long as you set the right Boolean but that's kind of the very simple example of how all this works if

you kind of understand it great if you're still a little confused don't worry like I said this was just me showing it to you just our introduction we're going to work with this in future apps and get more in depth more complex like if you look at our view model pretty simple right we just have one variable that changes and then you know we broadcast a Boolean when it changes but

you can imagine like a real app there's going to be Network calls in here uh maybe there's other functions with other logic so these can and will get more complex in this course but again I just wanted to show you what it was all about let's move on to the next video just like last video was your first little taste of mvvm this one's going to be your first little taste of interacting with

UI kit and we do that through UI view controller representable or UI View representable and the reason we have to use these is like I said 100 times now Swift UI is so new so it's not fully built out yet so for example in iOS 14 Swift UI just got support for map kit and Sprite kit so now you no longer have to use UI view controller representable for like your map kit stuff but

there's still a lot left such as the camera which we're going to do in the next app that doesn't have Swift UI functionality yet and there's many more the photo picker so for that we need to integrate with UI kit and that's what I'm going to show you here however I do suspect over the coming years right just like map kit and Sprite kit got introduced this year over time you know

I do believe the need for this UI view controller or UI view representable is going to I don't know if it'll ever go fully away but it'll become very very Niche whereas most of the common you know UI kid stuff we'll get Swift UI counterparts but for now and until that actually happens this is going to be a key skill you're going to need to know okay so big picture what's going on with

these UI view controller representables and uiv representables by the way that's a mouthful I'm just going to say UI view controller representable just know that I'm talking about both you would use them accordingly if you need a whole view controller use the view controller one we just need a view use the view on all right so basically what we're going to create is a swift UI view that

conforms to UI view controller representable and that view like you know every view has what we're looking at here this VAR body some view right in Swift UI every view has a body well with the body of the UI view controller representable is is whatever view controller and UI kit we create right okay so that's what's happening this body is getting replaced with the UI kit view controller

so let's create this kind of uh container view if you will so we'll do command n and apple Frameworks so file hit next we'll call this Safari view because that's what we're showing the UI kit component we're using here is the Safari view controller right at the moment there is no Swift UI Safari view again I'm assuming there will be in the coming years but right now there's not

whoa whoa whoa whoa quick Interruption because after I filmed edited upload recorded all that stuff this entire section uh I randomly discovered that oh yeah iOS 14 did introduce a link that kind of does with the Safari view controller functionality does no idea how that slipped by me when I when I saw it I was like how the hell did I not know about this so anyway I'm leaving this

in and just putting in this little insert because the lesson Remains the Same right the lesson isn't about Safari review controller the lesson is the introduction into UI view controller representable so call this Safari view hit create and here we are so we need a struct just like we're creating a view except so Safari view except we're not going to do view here right we're going to do UI View

UI view control and I'm not getting it because we didn't import Swift UI that's a key thing here so UI view controller there we go UI view controller representable now when I hit return it's going to say I'm missing a few things because in order to conform to this UI view controller representable we need two functions right one of them is going to be called make UI view controller

and the other as you may have seen would be update view controller now these boilerplate functions that autofilled for me doesn't have all the information correct right it kind of gave me the generic information right like for example we don't want to return some UI view controller we want to return Safari View and we're not getting that because with Safari you need to import

import Safari Services right there's a framework so do command B now I should get a Safari view controller here yeah there we go SF Safari view controller that's forgot that as well now our context is just the generic context we want this to be a UI it's going to be a mouthful view controller representable context right and then

it takes in what we have here we have our safari View and again we're going to do the Deep dive later I'm just showing you this really what I want to get across is the two main functions we need and what's actually happening in this Safari view controller we'll get into the Nitty Gritty in the next app so can you guess what make UI view controller does it makes the uiv controller that

is going to take the place of our body in our view so here's where we create that view controller and the reason why this is a really straightforward simple example is because you know if we had our own custom view controller of course we would have to build that and make that that's what we're doing in the next app this one you know a safari SFS fire view controller is kind of built into

UI kit so it's just one line of code it takes in a URL uh you know what we want to make this generic right I can't hard Kodi URL because every framework is going to have a different URL so our safari view needs to take a uh we can make it let let URL and it's going to take in a URL object

so now we can just pass that URL into the make UI view controller so whenever we initialize a safari view we'll pass in a URL that gets passed in down here to the safari view controller now we need to update the update UI view controller here again we're not doing just a generic UI view controller type the uiv controller type is a safari or SF Safari view controller right

that's the type of view controller we're using and then the context again is going to be this same context that we put up here this mouthful UI view controller representable context and then we pass in our safari view here and then the update view controller is actually just an empty implementation you have to put that there for what we're doing because we're not actually

updating anything on the Safari review controller it's empty but this should what am I missing but I thought this should work what am I missing there we go build succeeded that's why I always do command B all the time just to like refresh my errors so quick overview again just the introduction you create a kind of container uh Swift UI View and it conforms

the UI view controller representable let's dig in here just so you understand what this is a little bit well again we're going to do the Deep dive but so Swifty live view controller representable conforms to view right where self.body equal equals never so this is a view that we can use you know in our Swift UI code here so that explains why we're not conforming to view here

and again the body of this view we're going to make a UI view controller uh for the body of the view and that's what we're going to show so this is the basics of how you dive into UI kit again creating our view controller is just a built-in Safari review controller that's why that's so simple one line you can imagine if you had a more complex view controller you'd have to do

more code here we're going to do that later okay so now that we have our safari view move that up here let's go to our detail View and if I pull up the design you can see that the Safari view controller slides up in a modal sheet just like our detailed view so back to the code we need to

add a sheet onto our detail view so here we can dot sheet and again is presented so like I said we need a binding bull we don't have that bull yet so we're going to create that bowl on our detail view called at State VAR don't make it private VAR so you're at State variables that are just unique to one screen should always be private so private VAR is showing Safari View and again that's going

to equal false by default we're going to flip that to True when we hit the learn more button so let's do that first here so here's our learn more button right our AF button that we created so our action for the button we want to do is showing Safari view equals true so now when we tap that button flip that to True again the declarative right we're just changing a source of truth of data

the UI reacts so is presented now we want that to be based on dot is showing so far I'm sorry binding is showing Safari review so again whether the sheet is presented or not depends on what value is showing Safari review is and the content we want to pass in is our safari View right and then remember we made Safari have you taken a URL so here's where we create our URL and

the URL we want to create from string right let's find that here right string and the string we want to pass in is framework dot URL string right we already have that in our data now uh you can go like this if you'd like to live dangerously uh that is force unwrapping it and you know just assuming our URLs are always going to be correct or you can you know do some no coalescing give it

a URL again pass in a string and you know you could give it this could be some website you have on your server like seanallen.com not found and you can have a nice little empty state or you could send them to some default website if that makes sense like we'll send it to apple.com we know that's going to be good so we'll Force unwrap that or if the URL string on the framework doesn't

work you could pop up in there again there's tons of different ways you can handle the errors we're going to get into error handling in the final app of this course so again to recap what's going on here our sheet is going to be presented based on our is showing Safari review bull what we're going to show is our safari view which again is our UI view controller representable

here when this initializes instead of having a body like the view has it's going to make a view controller The View controller that it's going to make is Safari view controller with the URL that we pass in so if we go back that's what's going on down here we're passing in our framework URL string and if that is nil for some reason uh you know we'll pass in apple.com or handle the air

and again this all gets triggered when we tap our learn more button we flip that to true so let's hit stop run it okay let's tap on class kit learn more there's our safari view controller that pops up and the nice thing about Safari view controller is that it uh you know it has all this done button

remember how we had to create our own x button to dismiss it uh well now it has its own done button so you know you can learn about class class kit real quick uh okay I'm done and then it'll slide uh back down and you can either slide this down or hit x one quick thing I want to show you before we

wrap up this this video is just a little slight variation we can do on sheets right because like when we hit metal right it's pulling up this card that has this Auto dismiss swipe down you may want that you may like that you got to add your button that could be your style well maybe on our safari view controller we don't want this card here we want it to be like full screen right just now

maybe we like the way that looks so so new in iOS 14 here let's stop this instead of sheet literally the only thing that's different is you do instead of sheet dot full screen cover as you can see and you're going to get the same if I hit return it's going to mess me up so we'll do full I'll just

type full uh screen cover like it is and literally none of the parameters change they're all the same you just go from sheet to full screen cover so now when we run it and I guess I'm just running it on simulator from here on out uh now watch what happens when we pull up our safari view controller because that's the one we made full screen so we've got a health kit learn more now our safari

view controller is full screen right it's not that little card that takes up 98 of the screen so you know depending on what look you're going for in your app on the navigation you know use a sheet or use a full screen cover whatever's best for you as I showed it is literally just changed that from full full screen cover to sheet and vice versa and you get that behavior that is new in

iOS 14. uh kind of suck because if you wanted full screen cover before iOS 14 like in iOS 13

iOS 14. uh kind of suck because if you wanted full screen cover before iOS 14 like in iOS 13 you had to do a lot of like hacky workarounds it was rough now it's just a simple simple change but again that illustrates how swift UI is still being built and it's so early a lot of very like

basic stuff like that like wasn't in iOS 13 just came in iOS 14 and who knows it's going to be an iOS 15 16 and Beyond so again super early but that is how you go from a sheet to a full screen cover and that wraps up our introduction to UI view controller representable and diving into UI kit and again we're going to build a barcode camera app that passes data with coordinators you know

gets really into that topic in the next app but just wanted to show it to you here that wraps up this video next video we're going to do some quick refactoring and then convert this grid into a list and the cool thing about that is it's pretty quick to do uh so let's do it we left off last video basically wrapping up the app with our uiview controller representable showing our safari

view controller in this video we're going to do a last minute refactor pass and quick little project organization and then we're going to convert this into a list and navigation you know detail view so let's get on with the quick refactor because we got all our files here so let's go file by file then we'll reorganize it like in the folders here so our view model here pretty simple not much to

do here one quick styling thing I like is if I have a simple did set or will set whatever um and it's on one line like this I like to just clean it up if it's like super simple right you don't want to make it the one line terribly hard to read and super long but this is a real quick Short Line super simple thing so I like to put that there in that circumstance personal

preference just me all right next file let's get rid of our preview here because we're not going to need that we need to focus on the code um so okay so what we can do here is this grid items even though it is directly related to how the view should look again I kind of like to put this into

the view model so I I cut that let's go back to our view model here and Below these variables we can just say let columns equal that so now in our view again I like the view to be as clean and like dumb as possible so it's very easy to read for one thing so now instead of columns we just do

view model dot columns there we go we're getting the same thing there and then let's keep our let's actually bring our preview back up because anytime you're you're refactoring you definitely want to make sure you don't break stuff right so hit resume on our preview try again preview work with me preview try again no play okay okay I guess we're giving up on previews here let's get

rid of that we'll just do it the old-fashioned way and this is what I was talking about how previews are great like when they work okay so running on the simulator the old-fashioned way refactoring our columns didn't break it we're good cool okay so like I mentioned earlier when we built this I feel like this is nice and clean very simple no need to refactor there um same thing sheet

is presented no need to refactor here scrolling down okay here we have our framework title View and remember what I said about project organ this is used in multiple screens right it's used on our grid and it's used on our detail so I want to put this into its own file so we'll do command X there Apple Frameworks command n new Swift UI view next call this Frame uh work title View

create cool there it is and then in my body actually I think I copied the whole thing yeah so we'll just so we'll just overwrite the whole struct there framework title view good to go missing an argument for the parameter and call uh that's right it takes in a framework right and then we invest we have our mock data dot sample framework and then back to

our grid view to make sure uh it's gone yep so our framework grid view just shows our grid View and we have our separate file here for framework title view cool and again I'm just going file by file so we did our grid view that's good our framework model pretty straightforward right just a basic model and then all of our mock data cool our detail view see if there's anything that

really stands out here you could let me do a command B you do a command B to see if I can get my syntax highlighting back xcode there we go uh yeah let's do this right because this x right if I pull up the the canvas on the preview here on our detail view I resume right you can imagine in your app you're gonna have a lot of modal display well you could have a

lot of modal displays so this x could be a common thing you need to put you know on multiple screens so let's refactor out this uh button H stack here we'll actually keep the padding as well I mean you that's debatable you could add the padding as you needed on each screen or you could include it because you know you're pretty much going to need it because if you don't put it it's going to

push it all the way to the edge we don't want that so I'm going to command X there new file command n Swift UI view we'll call this uh X dismiss button create there we go and then paste it into our body HDX get a preview of that nice little X would be pretty basic okay forgot

something oh that's right we have to pass in our binding right so I need a at binding VAR of is showing detail View and most likely in your app you're always going to want to dismiss your model like it's kind of the whole point of this x button so maybe you name it something different maybe it's just like is showing modal right to be more generic because it might not always be a

detailed view but that's you know just a little tip there so you don't actually give the your binding things of value you get passed in a value so you just tell it it is a bull so now that uh is good whoops I gotta again the previews remember the previews are always going to get you and because it's a binding we actually have to pass in dot constant and then we'll say false for now

so hit try again let's get our preview of our nice little just X cool there it is kind of a useless preview but there you go so X dismiss button is now refactored so let's go back to our detail View and use in this space here x dismiss button and then we need to pass in a binding right is showing

detail view or if you renamed it to is showing modal probably a better name uh now we want to pass in our binding of dollar sign is showing detail View and I want to point this out because what's happening here and there's there's this is where it can get kind of crazy by passing bindings down many many layers of views and if you find yourself doing this a lot there's the environment

object which again we'll talk about in a later video you know passing it down to one child view is basically a must right that's the whole point of it once you start passing it down to two and more that's when you want to consider environment so in this case we're now passing this is showing detail of you binding down two layers here right because our grid view right back to the grid view

the grid view passes the issue in detail view to the detail View and then the detail view passes that binding down to the X dismiss button right so we're going down two two layers here but the point of binding and I hope this really illustrates it is as long as you keep passing the binding down no matter how deep you go they're all going to be tied together right because they're bound so if I

could be five uh you know levels of views deep and if I switch is showing detail view on that view it's going to go all the way up the binding all the way up to like the top level you know this this framework grid view to change it again that just illustrates how it works if you're passing it down five views you should probably use environment which is different but again

hopefully that helps you understand uh binding a little bit more so we just refactored out our X dismiss button here cool so now our our detail view looks pretty good you could argue to refactor out like uh call this like a body text to always have font body and padding you could do that if you find yourself reusing that a lot we're going to leave that for now that's probably overkill

for this uh little app in our safari view again pretty straightforward there so we just went five our AF button yeah nothing nothing to do there it's just our button so we just went uh file by file and kind of did an extra little refactor now let's start like organizing these right so organization hugely subjective and there's not really a best practice out for Swift

UI yet what I'm about to show you is just how I organize my projects and what I have found easy to to understand but that is very subjective you may find your own style of organization that's perfectly fine just use mine as an example take what you like leave what you don't but here's how I do it so I create a new uh group I'm going to call this screens even though that's kind of

a weird word in Swift UI everything's a view but this helps me like bundle all the views in like a certain screen in in one area so I do screens and now in this folder I'll create a new group I'm going to call this uh frame work grid view right so this is our grid View and I'm going to put in

the grid view I'm going to move this out here so you can see it right so we have our grid View and our grid view model well those both go in the grid view folder right because they're both related so that way when I open up my grid view folder I see I got my view model in my view they're all right

there I don't separate like a separate view model folder because now you're going back and forth is confusing I put everything like right where I use it the most so the other screen we have and the reason I like doing this is because like I can go like screen by screen and see what I need right is the frame work detail View cool so that is just the framework detail view goes in there we don't

have a framework detail view model that's fine and then I kind of like to put these in the order that they show right so like the grid view is first then you go down to the detail view so now we're well now in the Apple Frameworks let's build our model folder so right click new group and call this model cool what goes in the model Frameworks there we go so like I said I have my screens

folder but that's for like the overall screens right but we have these reusable views right AF button X dismiss button framework title view so I usually create a new uh group called well not in model let's delete that so make sure you click on Apple Frameworks new group now I call this

views and this is just overarching so within views new group I'll create something like uh buttons so right so we have our X dismiss button and our AF button so that can be dragged into buttons and then in here you can imagine I would have like you know text labels images like any custom views I kind of give their own folder so one of the custom views here is just view so I understand this is

redundant but you know like our framework title view is just a view so that type of stuff for me goes into the sub view of views I get it and then usually what I create uh to keep things separately is a new group and I call this UI kit components and that's where I put all like my UI view

controller representables that sort of stuff so we'll drag this Safari view up here and the reason I do this and I want to keep these separate and compartmentalized is because like I said I expect this UI view controller representable to not fully go away over the years but become less and less right like Safari view controller perfect example I very much expect a swift UI native Safari view

very soon so I want to keep this separate so when I come back to my project like I know like what I can replace as this new stuff comes out right it's all in my UI kit components folder so that is the reason I separate uh all of that so that's my basic folder structure again views will have views buttons text images you know whatever custom views I've made we'll go in that views folder model

and then screens where I bundle the screens and their view models and if there's any other view that's like only specific to that screen I'll put it in there as well so that's a little bit of project organization little bonus now to wrap up this video Let's convert this thing to a list uh it doesn't take long at all one thing I always got to do though and this is just xcode because

we moved all of these screens around like we messed up the file pathing so we lost our our syntax highlighting autocomplete so usually I just quit xcode and reopen it so that's what I'm going to do right now all right so I've quidx code reopened it we got our syntax highlighting back that usually happens anytime I move files between folder structures all right so let's

convert this to a list actually wait wait wait big stop I forgot before we do that because I want I want this grid app to persist for you because we're going to come back to this later go into your finder here wherever you have your Apple Frameworks project saved so in this folder I'm going to do right click duplicate right we can call this apple Frameworks you know list and

that's why you have these separately right so now make sure you open up the duplicate that's called list so that way you have that all done saved not touched and you have this list one separately you can reference them both uh it'll be much better that way so now open up your your list one okay pulling up the design the first major change you're going to notice is in our framework title

view it's no longer a v-stack it's an H stack right it's got to go horizontally because of the list so let's go to our our view here framework title View and instead of v-stack let's actually open up our preview so we can see this here okay we'll make this smaller here okay so instead of a v change it to an H pretty straightforward cool uh we may come back and mess with the text size

um but just like that we went from an h v stack to an H stack that should be good now let's go to our grid view here right screens uh framework grid view grid view okay so what we can get rid of first is the scroll view right because a table view or a list if you will has uh scrolling by

default so what I do is I kind of come to the bottom first okay that's my scroll view cool let's delete that one and then delete scroll View and then the neat little trick here is if you highlight your whole struct here control I that'll line up any you know bracer issues that you have

okay so the next thing you want to do is let's get rid of our our lazy V grid right we're not doing a grid so let's get rid of the lazy or lazy V grid and just call it a list pretty simple we're still using our four each because the same principle applies right we want to iterate through our array

and create our cells accordingly however the list has a built-in tap gesture like we don't you don't need to add the tap gesture there so let's get rid of that tap gesture uh however what a navigation view has is what's called a navigation link so again on the list when you tap it we're gonna use the navigation controller to slide on the detail view so the key here is that each framework title

View and side note um if you're doing a list you should probably name this framework sell or something like that um so anyway we'll hold off on the naming uh you know because it could be different for a list just want to get the functionality in there so you need a navigation link that's what kind of triggers the the Segway here well it's not a segue that's storyboard it's

already confused you with my lingo to trigger the transition to the detail screen so let's call it a navigation uh link here link cool that takes in a destination and you can see there's a whole bunch of stuff you can do I just do destination and again this is another one of those cases where autocomplete is confusing so I just do destination because all that takes in is a view we want to go

to and for that we want to go to our framework detail view right and we want to initialize that with a framework and again this is this framework that we're iterating through so we want to pass that framework to the destination View and then is showing a detail View again same thing viewmodel

dot is showing uh detail View and then that destination needs open and close curly braces and X there we go so that should be working I'm going to get rid of the preview real quick just so you can see the code kind of how it should look put our parameters down there so trying to make this look as neat as possible here right so we have our navigation link it takes in a destination

what that destination is is whatever view you want to be your detail view for us it's our framework detail view our framework detail view takes in two parameters right it needs to know the framework and then he needs to know if it is showing detail View and that's we're passing in The Binding really this is like the exact same thing that we're passing into the sheet here right it's

just a little different and on that note we're not we don't need this sheet anymore so we can delete that because we're not presenting a sheet we're presenting a detail view so we essentially moved all the stuff from our sheet up into here into our destination on our navigation link so the navigation link has the open and closed curly braces and inside that we have our framework title

view we're basically saying whatever is tapped on the list which is our framework title view that's when you trigger the navigation link and I'm going to actually make my code smaller for a second just to show that like when you're actually coding on your screen and you may see it it's actually not that big um it's just I got to blow up my font so huge trust me it drives me nuts how my code

looks when I when I'm teaching um okay so now if we run this on the simulator here and here we are not looking a hundred percent like I want it to look but the general functionality is there let's tap on carplay right see we're sliding the navigation controller over to our detail view you can see we get the back button uh we still have our X here so this doesn't look quite right so

we do need to make some adjustments here so let's go back the first thing I want to do is these are quite big at least for my taste we're still using that 90 by 90 frame for the image that we hard coded so if you like this big look cool leave it like that I actually want to go to our framework

title view here and instead of 90 by 90 let's do 70 by 70 just to make it a little smaller we'll run that on the Simulator take a look at how that feels here okay we're getting there the icons are smaller that I like now you may notice there's a lot of padding on the top and bottom and this is

all subjective you can play around with this but I want to show you how you can tweak this a little bit so instead of having the padding on the entire H stack of our framework title view let me pull up the simulator again right I also want a little more space in between the icon and the label here

so I'm going to put the padding actually command X I'm going to put that on the text right so that'll give the text a little padding space it out a little bit let's run this I know I'm doing the old-fashioned way the running but I've been having issues with the uh with the previews so now I kind of like the way this looks a little better now let's fix our detail view because

again if you click class kit like everything's pushed down to the bottom so let's go to our our detail view here framework detail view now we don't need that x button so let's get rid of that and we'll keep the spacer so let's just get rid of the X dismiss button that we're doing give it a run see what it's like you could probably actually go to canvas for this but

you know I'm in the habit of this class kit there we go no more X things are looking good see AR kit there we go so the last thing we may not want this blue framework to write that back button right see if I click on something it's blue well let's make that uh white or actually label right because we

want it you know black and light mode and white and dark mode so the way you can do that is on your list if we go back to the grid view or I'm sorry not on the list but on the actual navigation view uh itself right because that's where the back button actually is we could do dot accent color and we can pass in color with initializer of dot label

and you can see now we'll run it now our back button will be white in dark mode and black in uh light mode so let's say catalyst there you go you see our Frameworks is white it's not that blue so that's how you adjust that make sure our smart review controller still works still works as expected now we can head back there you go so as you can see that took just a couple minutes

a small little tweaks here and there and we converted a grid View to a list view now if you're coming from UI kit you can imagine trying to like rip out a collection View and replace that with the list view would have taken a lot longer so that is a nice little benefit of Swifty why is like switching between all these things with relatively little effort so the last thing

I want to leave you with in this video is the challenge this challenge is going to be a little bit different so let's let's click on uh Swift UI here right let's go to Swift UI keep keep the theme going so this is our detailed view um not my best work not gonna lie as far as like design

right it's very very plain not much is going on here but this is where I want to challenge you this is a little bit of a design challenge but it will also give you a chance to play around with the layout of Swift Dy so my idea here is redesign this detail view right you can completely change the layout keep the data the same right we just need the name of our framework the icon the body

and the learn more button but play with the layout that completely reinvent it and see what you can come up with and what I think would be cool is if if you came up with a good design you shared it in the slack channel that way other people taking the course can see it and then one they can get inspiration from your design or two they can get practice building a bunch of different

cool designs on this detail screen now I know there's it's pretty limited it's not like you can go crazy with it but I'm curious to see your creativity what you come up with for the screen and then hopefully other people can build it as well so I think that'll be a fun little Challenge and that finishes off our Apple Frameworks app hope you learned a lot as you can see we're

slowly expanding our knowledge and the next stop we build the barcode scanner it's going to be all about that UI view controller representable and actually passing data from UI kit to Swift UI in this video we're going to discuss the iOS 15 updates for the Frameworks app and there's really only one right again these pretty simple apps in the beginning there's not much there but I want

to take time to showcase the new button system in iOS 15. as you can see here in the lower right we have our learn more button that we customized to refresh your memory here I'm going to go to the Views buttons this AF button right we have a text and we're customizing with all these modifiers and there you go well Apple introduced a new system that gives you a lot of the default looking Apple

buttons kind of built in out of the box as you can see here there's some pretty basic Styles where you have the plain gray tinted filled there's a nice WWDC video that I'm going to link to really specializes in UI kit for that video but there is a swift UI equivalent and that's what we're going to talk about in this video so again the whole point here big picture if you want Apple

looking default buttons like they belong in an iOS app this is probably the way to go the new way that I'm about to show you however if you want your own super crazy custom buttons that you want full control over should probably stick with the old way that we've already done with AF button I should even call it the old way I should just call it the more customizable way because again

the new way just basically gives you Apple looking buttons alright so let's talk about that so this AF button where do we use that right we use that on the framework detail view right this learn more button down in the lower right and then here on line 30 is where our button is and you can see for our button we're using the label of AF button where we pass in the title right that's what this

AF button is Right passing the title and that's what we give it okay refresher over so now there's some modifiers on button itself but we still have to give like some content to the button here so I'm going to comment this out and that's another thing I should point out like I'm not going to go back and delete AF button even though we're not using it strictly for learning purposes so

you can go back and see the difference you know in a real app if you were converting to these buttons you should probably delete and get rid of your old code right it's called Zombie code code that's around that you're not not using and over the lifetime of a project that really adds up over time so you want to make sure you're keeping that under control so your code base Isn't So cluttered

with like are we even using this anymore and it's confusing and you're not sure so once you delete stuff uh get rid of it for the most part there's always exceptions of course but anyway I'm going to keep it in there for now framework detail view now what I want to put in here is let's resume

this so I can see this in real time you could just put a text if we wanted to keep the same exact look but I'm going to add a little spice to it right we're going to put a little image in there so this is going to be a label as well and make sure you do system image name not just image name

because remember system image name is what gives us the SF symbols if you had your own custom image then you would you know have to load it into your project and use that system image name is what we want to do so again this is still going to be learn more the label is what the text is again

same as what we had on our AF button system image the SF symbol is going to be book dot fill and I just know that that's SF symbols you can look it up I did that to save time but I'll zoom in on our simulator here you can see that's our basic learn more button we haven't added any styling

to it right so that's why it looks like that and I put that little book there for the learn more if you want a different image explore have at it now the new modifiers for the button is where the new system comes into play so the first modifier we want to add to the button is dot button style here right and then we want to do we get bordered bordered prominent borderless plain so this plane

is what you see there bordered we'll do there you see the default we get okay come on preview oh see bordered is only available in iOS 15 or newer this is what I was talking about in the overview video about how a lot of the new Swift UI stuff requires iOS 15. so let me go to the project forgot to do

this in the beginning project here iOS deployment Target make that iOS 15. and if you're wondering how do I you know add this new stuff but still you know support less than iOS 15. well that leads to a little bit of messy code because I'm not going to go into it now but there's these conditionals

where you can say like if this device is on iOS 15 run this code if it's on iOS 14 and Below run this code so you're kind of like duplicating your code to do things twice that's why most apps like they won't adopt the iOS 15 stuff until iOS 15 is the minimum deployment Target so a lot of iOS developers they see all the new iOS 15 stuff but they know they can't even use it for

another year or two but luckily for us we're in an educational environment we're going to support minimum iOS 15. so Apple Frameworks iOS 15 and then now that we're supporting iOS 15 do a command B to make sure everything's all good okay good to go back to our framework detail view this error is no longer there and then now our border button if you can see has a slightly

gray background on the border that is the default now we can style that but that is one style of button that's that gray style you may have seen buttons like this again all over Apple's default apps but let's customize this a little bit so we can do dot control size so you see it's kind of small again large mini regular small we'll go to large you can pick that now you can see our button

got bigger I'm going to click off of it to get rid of that red square but now you can see what our button looks like so you can customize this a little bit but you're getting that apple look and feel out of the box we didn't have to mess with Corner radius we didn't have to do anything like

that and now we can customize the colors a little bit so I can do dot tint and then dot red that'll give us the red tint and I'll get off it so get rid of that red box but you've seen these buttons in iOS 2 right where you have like the 50 opacity of the same color background with the same color

as the foreground of the letters now the reason these buttons work well is due to contrast ratio usually when you're using the same color you're going to get a good contrast ratio for people that are colorblind you can imagine like a a yellow button with white letters those white letters are really hard to see so some colors in white don't really go well this is a nice way to ensure great

contrast ratio and that's the bordered style right so we saw the gray background and then the tinted background but how do we get the button that we had right well that would be bordered prominent right and now we get that you see and the tint is red that's the background our foreground color is white by default but now you can see we get a button that looks like how we had it and if you

do want to change the foreground color say you have some weird color scheme right you can do that foreground color we'll say dot uh yellow and the foreground color will be your text as you can see now our button uh looks like McDonald's right but you can see how you can customize that now if you do want to customize the shape a little bit you can do button border shape hit dot so you get

automatic capsule so capsule would be as you can see here that typical capsule look that you've seen that a lot of the places or you may have noticed instead of that capsule you can do dot rounded rectangle and you can determine the corner radius I don't know I'll just put 20 in there right if you do have a specific Corner radius so you do have the possibility to customize it

a little bit but you can see just with these few modifiers we can you know do everything we need to do and again that is to get these uh Apple looking buttons and I'm going to comment out I'm just going to comment it out so you see this in the uh the code here but I'm commenting out the Border

shape I'm going to go back to dot border because this is the look I like this is how I'm gonna make like all my buttons from here on out in my apps like I really like that tinted look now anytime you have a bunch of modifiers on a button like this I like to abstract that away in like a custom modifier this was just your introduction into this button system we're going to deal with that custom

modifier in the appetizers app when we do that for our buttons there but this was the introduction highly recommend checking out the wwc video I will link below and that's all we're going to do in the Frameworks app because again there's not much here but this was a good opportunity to learn about buttons iOS 16 introduces a fundamental Improvement to Swift UI and that is the good

old navigation view right used in so many apps used so many places is now deprecated in favor of navigation stack and navigation split view so a navigation stack is the typical navigation you're used to they call it Master detail navigation where if you tap on something a view slides in from the right and goes on top of the stack pretty typical navigation split view you've

seen this before too that's the two and three column layouts now of course you could do that navigation in Swift UI now but the reason for this Improvement is it's a new data driven navigation API so that means how you navigate is based on your data type I know that may sound confusing let's actually convert our Frameworks app to that Master detail navigation type rather than showing

a sheet from the bottom in order to Showcase this new data-driven navigation API now to be clear there's nothing wrong with showing a sheet like we're currently doing I'm just inverting it to the master detail to Showcase this new way of doing things okay so our navigation view because we're showing a sheet the only reason we have this in the navigation view is so we can get this

pretty navigation header that says you know the Frameworks so let's convert this to a navigation stack and you'll notice you know nothing happening oh navigation stack is only available in iOS 16 or newer I forgot the most pivotal First Step click on your project go to Apple Frameworks make this iOS 16. now before I go on my rant here let me update our Target as well to iOS

16. okay so we're minimum supporting is IOS 16. now you may be thinking well a normal app has

16. okay so we're minimum supporting is IOS 16. now you may be thinking well a normal app has to support iOS 15 in previous stuff that's fine this is educational but my rant is that let me do a command B to get I can't think when xcode's yelling at me with red stuff you can conditionally support the iOS 16 stuff like this navigation stack and still support iOS 15. that's how most

apps will you know support the new stuff while still supporting old stuff however that means you basically have to write the code twice right you have to do all the new iOS 16 stuff in our case it would be all this new navigation stack code and then we'd have to have this giant if else essentially right if iOS 16 do all the new navigation stack stuff else keep all the old iOS

15 stuff so the point I'm trying to make here is you don't always have to automatically support the new iOS 16 code right the old navigation view will work fine for a couple years that's the beauty when Apple deprecate stuff it just doesn't stop working automatically they let you know they say hey this navigation view is going to be deprecated you know they don't tell you exactly when most

of the time but you usually have two three four years before it stops working so just so you know you have time to slowly update your code base you don't have to do everything right away and why you probably wouldn't want to update all your navigation views to navigation Stacks is because this is such a fundamental part of the view that your code would be like a nightmare you the giant

if else statements everywhere so my recommendation would be not to convert all your old navigation views to navigation stacks and tell iOS 16 is your minimum Target most of the time it's just not going to be worth it okay so now that we have our navigation stack let's get rid of our sheet here because we're no longer doing that and then we no longer need this selected framework right because

we're not doing anything on tap gesture so get rid of that tap gesture and let's go into our view model and get rid of all that stuff right we don't need issue and detail view we don't need selected framework so we just need our columns there it's a back to grid view make sure we get our preview back good to go so now like nothing happens right we tap nothing happens this is when the sheet

would show up but nothing happens now okay so now we want to implement that Master detail view with the new navigation driven API so to do that in our four each right normally we had the tap gesture on each thing now we need to have a navigation link with a value in the label so the value is going to

be our framework remember so the value is the data I'm going to explain all that at the end let me get through the code and then I'll you know do my little summary so the label is basic our framework title view this is whatever the UI is for our navigation link so now you'll notice everything turned to Blue that's the default for the navigation link well we don't want that if we go

up into our view folder here our framework title View for the text let's give it a DOT foreground color and then here's a little trick here right we want to dot label because we want it to be white and dark mode in black and light mode but Swift UI color doesn't have just a DOT label so you

can do color and initialize it with a DOT label this is how you get to the UI kit semantic colors if you're familiar with UI kit you like it has a bunch of semantic colors that look good in both light and dark mode and they have like secondary system color or secondary background they have all

those so that is how you get to those so that's what we want there with the label so if we go back to framework grid view we should lose that blue tint there we go that's how it's looking so now when we click it still nothing happens but this is where we want the master detail navigation to slide on the detail view down here after our navigation title we do navigation destination

and then this is the type again it's data driven navigation which means it's based on the data type our data type is our framework right this would be whatever type we had whether it was a string or our custom type of a framework whatever data type you're doing so it's going to be framework.self

and then our destination well hashable it has to conform to hashable which our framework already does so this is going to be the framework that we tap and then now it is going to be framework detail view which takes in whoops okay so we still have this is showing detail view let's go to our framework detail view we no longer need that that is showing detail of you actually we can clean

this up a little bit let's go to the preview so if your preview is not working we'll just do this so I don't need issue in detail view because remember that is how we dismiss it I no longer need this x dismiss button let's see if we get a preview back nope okay I no longer need that X dismiss button

because we are in the master detail navigation I don't need the spacer at the top because that had to do with the dismiss button okay so still not showing the preview let's go back to the grid view here here now let's initialize this framework detail view it just takes in a framework and that is going to be the framework that we pass in when we tap it so essentially whatever framework we tap

we're going to navigate to a framework detail view with that framework okay lost the Swift UI preview let's see if my project builds build failed what did I mess up is showing detail View and so okay yeah previews so my framework detail view doesn't have the ISS showing detail view parameter anymore

so see if that works there we go okay so now you can see the UI of our detail view that will get pushed onto the navigation stack so back to the framework grid view refresh the preview oh man these previews let me try running running the app here uh I see what I did line 26 I missed

the period wow that little thing you know just completely uh destroyed xcode anyway now when I tap on this you get the master detail navigation right it's slid in from the right that is the navigation stack and again let's talk about the why this data driven API is helpful because yeah with just our framework Simple app or we just have one data type of a framework seems you know you

know you might not see the value in it however a more complex view like maybe like the app store that has a bunch of different you know horizontal scroll views a bunch of different collection views or maybe our app had a bunch of different types right maybe we were making a developer app where we had a horizontal scroll view of Frameworks and we had a horizontal scroll view of like

developer software with like xcode SF symbols if you had another one of you know recommended blog websites so you can see we have all these different data types on one screen and you're navigating to different screens based on that data type so that's why this data driven navigation API is so helpful for situations like that so that's the new navigation stack in iOS 16 Swift UI and

again the main thing is that it is Data driven it is based on your data type like our framework and it really shines you really see all the benefits of it when you have a screen that has multiple different data types and you're navigating to different screens based on that data type the app we're going to build in this section focuses on passing data from UI kit up to Swift

UI via a coordinator in delegates if those words didn't mean anything to you we're going to dive into it but as you can see on the screen here what the app does it's a barcode scanner so we utilize the camera this is what's not in Swift UI yet this is why we have to integrate UI kit to use

the camera so you know we'll just scan a barcode and we'll display the barcode that we saw so as you can imagine the barcode and any potential errors that is the data that we're passing from UI kit up to Swift UI so we can display it on the screen and again we'll pass that data from UI kit to Swift UI using UI view controller representable and coordinators in this first

video we're just going to set up the UI but a lot of this is stuff we've done before so here's what the UI is going to look like this this dummy UI right it's not going to be connected but if you want to pause the video take a shot at building that yourself now's your chance we're going to

go through this real quick here in a second two things of note if you are going to try this on your own I am going to rename the content view to Barcode Scanner view so just a heads up and then there's one UI element that we haven't talked about just a little little hint there so there's one new thing but you may be able to figure it out if not we're going to build

it together right now so that's your last chance to pause the video if you want to try it yourself right now we're doing file indexcode obviously uh new project in it's an IOS app in the app hit next bar code scanner and again interface Swift UI lifecycle Swift UI app language Swift hit next

save it wherever you like saving it to my desktop and I'm going to hold option hit the Green Dot right there to make it full screen let's resume our preview let's get rid of our right pane again this is the typical setup we've been doing and here we are well preview is not ready yet but that will get ready there it is and okay I don't know why it defaults to iPod 7th generation like who

who even has that we'll go to the iPhone 12 Pro to get that set up we'll minimize it so it doesn't look super huge drag this over okay so the first thing I'm going to do uh is you know get rid of this content view now this is why I like putting out these videos as I go because I got a comment

um talking about the rename thing and I know about this feature right you remember me going on my rant how I just delete the file and create a new one I'm gonna I'm gonna try to adopt and change uh we'll see if this Burns me but we're gonna try the rename here so I'll also show you what's going on

so if you click into the content View and right click you can see refactor rename and then you get the code folding this was new in xcode nine like I remember doing the what's new in xcode and like talking about this but I guess what I didn't realize like I knew it changed the name throughout it but if you look up here it changes the actual file name right you see right there file name so

that is what the commenter pointed out that I wasn't aware of because that's what caused the file pathing issues okay I know I'm going on a bit of a side rant but let's just do this uh call this VAR code scanner View and right you see it's renaming it in my previews in my window group this is the app right where we have to tell it what view shows first and it's updating the file this

is the key new thing that I wasn't aware of that it updates the file name so in the upper right you can hit rename and there you go and look yeah our file got renamed our strut got renamed our preview got renamed and then again in the app file here that got renamed that got renamed so nice feature

um we'll see if I get burned on file pathing I'm assuming I'm not going to so maybe maybe I'll have changed my ways and learn something new as well by doing this course so anyway little tip there now this is the the dummy UI I'm going to build because we're going to put a placeholder in for the camera view we're going to hook all that up later but just to get the structure we're going

to build this again this is what I put up earlier I am going to go a little bit quicker through through this UI because hopefully this is a lot of review by now so I like to start here's the here's the text right I know I'm gonna have a navigation view so I kind of like to work my way right like

the the top view and I like to work my way down right so there's a navigation view if I spell it right put the a in there navigation view cool try again on the preview the preview always tells on you like when you mess stuff up try again okay preview whatever okay so in the navigation view I

know I'm going to have a v stack right if we pull up the screen again you can see just how the the elements are it's going to be a v-stack so now my v-stack cool and then on this v-stack I can put my DOT navigation title and this is bar code scanner there we go again I'm just kind of I'm working top

down just to let you know my thought process and like what's going on in my head right now so the next thing down is the kind of the dummy camera view uh Swift UI has what's called shapes um so I can just do rectangle right and it'll draw me just a square basically as you can see but we don't want the whole camera view filling up because we want to be able to display the

uh the barcode once we get it now of course you could redesign this however you like maybe you do want the camera view filling up the entire phone screen and you want to Overlay the label on it you know after we build this come back and play with the design if you like you can play around

with this but we're going to keep this just kind of like a window on part of the uh the phone so we want to give this a frame now here's where it's a little bit different right so frame has width height we're used to doing that well if we click into frame command click jump to definition you can see this is the initializer we've been using right frame height alignment well if we go down

you can see an extension uh here that has this Frame Min width I deal with Max width Max height right there there's a much more robust initializer on frame and that's the one we're going to use uh here so let's go back so so we can do Max with I'm not going to do the whole initializer because I'm

gonna have to like delete it again this is part of the what you'll realize with swift UI you'll kind of start to learn these initializers and you'll only just type out what you need because if you do autocomplete like I would have got like seven parameters there and I would have had to delete them it would have just taken longer so we're gonna do 300 there now here's the difference

right okay let me explain this as I go so I put Max height 300 because that's as tall as I want it to be right width is going to be dynamic I want it to fill the whole screen but height like I know I don't I only want it to be a certain height no matter what screen we're on right a barcode is

only so big so max width though you can do dot infinity and what this means is it will just fill the screen as you can see however wide the screen is it'll fill so if Max width Infinity Max height 300 you can see it's centered on the screen because that's kind of the default behavior of the v-stack it does look a little lower than centered and and the reason why is because our navigation

bar in the title is taking up a chunk so if you if you imagined uh like an imaginary line above under the barcode scanner now that space would be this would be centered in so again it is centered but if it looks lower than center it's because of our nav title okay so the next thing we want is the

words underneath the camera view that say you know that say scan label kind of like our our label spoiler alert we're going to use a label to do that I couldn't think of a different word other than label so now this is the new element that I talked about and this is also new in iOS 14. so

you now have a label element and once I put this in I'll tell you what it is right so it takes in a string and an image name you can see on the right so that would be if we had an image in our bundle or it takes a system image name which is a SF symbol which is this is probably the more common

one because it's very common now to have like a little icon and a label which is what we're doing here so the string we want is scanned barcode right because we're going to put the barcode under this in the system image remember this is an SF symbol so open up your SF symbols here I already got it open and just search for barcode and you see we get just a normal barcode and then like

a barcode in a viewfinder we're going to use the barcode in a viewfinder so again command shift C to copy that let's go back to xcode we will paste this string into there so see barcode.view finder

and then you can see it's real small down there but you can see that's what a label is so a label is like a little icon and then words and as you know that is a very common like pattern in like a lot of apps so that's why Swift UI just built it into one like UI element called uh label because

it was so common now labeled we can treat just like a text so we can do a font title because we want that to be a little bigger so let's dot font and we're going to make this dot title right so there you go that's how big it is now the last element we need is what we're actually going to display our barcode well if you see in the example it'll say not yet scan and then

when we scan it'll flip to the barcode we'll set up that up later we're kind of just setting up our the structure of our UI so we'll put some dummy data in there so this is just the text and for now not yet scanned because we're we are going to use that and uh as you saw in the

design I do want this to be big bold bright like you can't miss it so we're going to do doubled and then dot font large title like again we want this to be big you can see it down there it's already big and bold and then we can do dot foregroundcolor uh dot green for now uh again as

you saw in the design it's going to be red at first when we get a successful scan we're going to flip it to green and then lastly it's a little tight right there so let's add some uh padding there you go we're letting it breathe a little bit now one thing you may notice and this is getting kind of like nitpicky on the design it is a little it's pushed down a little lower now

in the previous design we were using spacers right to push stuff all the way to the top or push stuff all the way to the bottom we're not using any spacers yet so everything's kind of like huddled around the center of the screen right like it's like the center of gravity everything's pinned to the center it's not going to pin to the top or bottom unless we push it there with a spacer we're

not going to do that but I wanted to point out the differences in in the structure of the UI we are going to use a spacer however to add some space in between our camera view and our our titles down here so let's do that so after the rectangle let's go spacer right now this is not going to be

what we want but I want to illustrate what the spacer does it just pushes everything up or down you know it just takes up all the remaining space essentially but you can customize your spacers a little bit right so that's just the regular spacer we can give our spacer a frame so I can dot frame and width I don't care about the width we're only worried about the height so

get rid of that and and then the height let's make it 30 and again I dialed these numbers in get rid of this here now you know what that still looks a little bit too low let's do 50. and maybe

even 60. you can see how it's like moving up let's do 80. it's like slowly like moving up as we do that so you can tweak that and dial it in um let's let's go back to 60. that's fine the camera is kind of Center a little above that's what we want so that's our UI in place again we just have this random rectangle this black thing as like a placeholder for our camera view

we'll replace that uh in time but speaking of the camera view one thing I want to make sure we do before we forget uh is to update our privacy settings to give us permission to use the camera because if you don't do this your app's going to crash or if you somehow manage it not to crash it'll get rejected from the App Store so anyway uh in your info.plist

type in or hit this plus button here just type in privacy it's kind of searching and you can see like this is where you ask for all your permissions right if you want to get location permission photos permission contact permission in this case we're going to do camera permission so you can see it's right here camera usage so there you go now you have to give it a string and this

is what pops up in the alert so we'll say we need to use the camera to scan barcodes pretty pretty straightforward but you have to have this in your P list or else when you try to access the camera bad things are going to happen so back to our Barcode Scanner view our uis in place in the next video we're going to start setting up our camera view controller which is again down in UI kit so

if you're not familiar with UI kit this may be new to you if you are familiar with UI kit this will be a nice little going back home a little bit but that's what we're going to do in the next video we left off last video getting the structure of our UI in place in this video we're going to build this view controller which is our camera preview layer and capture session and all that stuff now

as you can see there's a lot of Av Foundation stuff going on here I'm going to go relatively quickly through this but still give a high level overview of what's going on and the reason being is I don't want to go too far down the rabbit hole of Av Foundation how the Cameron capture session works like that could be a completely different course right there's a lot going on

in AV foundation so again I'll give the high level but I'm not going to dissect every line and we'll go pretty quickly through the view controller because again the point of this lesson is communicating from The View controller to Swift UI not cameras and AV Foundation okay so first things first on your Barcode Scanner folder command n for a new file Swift file hit next we're

going to call this scanner VC for view controller hit create here we go import Foundation we're also going to need to import AV Foundation again this is uh anytime you're dealing with the camera video like you're gonna need AV foundation and I suppose we should probably import UI kit right I guess we should do that so anyway this is going to be a uh we'll do final class because we're not going to

subclass this final class scanner VC and that is a subclass of UI view controller there we go now actually before we dive into actually writing the code for this let me explain big picture how this communication works with the coordinator right we'll keep it super high level and then we'll dive in so the way uik communicates uh to Swift UI is basically through delegates and protocols

if you're familiar with that in UI kit this will you'll kind of understand what's going on if that's brand new to you you know I'll kind of explain it as we go but I'm not going to go too deep into it I have a video here that you can check out it's one of my most popular videos it's how a lot of people discover me through that video a quick disclaimer though it is one of

the First videos like I ever did when I started YouTube so I think I speak fast even here but I speak like three times as fast in that video so just a heads up but if you want to get familiar with delegates and protocols uh check out that video again I'll give the overview during this video but back to how coordinators work uh it's still kind of the same pattern except

the coordinator is like this relayer or translator in the middle right if you have UI kit UI kit will talk to the coordinator the coordinator will talk to Swift UI right so it's the same concept we're just putting something in the middle to relay the message like big picture that's all that's going on so let's actually set that up uh in this view controller so the first thing I want to do

before even like writing the view controller is set up our uh protocol here so protocol scanner VC delegate that'll be a class protocol I guess I should put the r in there for protocol I can't spell um so okay so when you're doing uh creating protocol this is basically just like a list of commands like you don't write any implementation here you

just kind of say what functions are going to be a part of this delegate right so we want to have one called did find whoops I guess it's a function function did find and then what we're going to do is pass in a barcode and that is going to be a string value that's what we get uh from the camera when it successfully scans a barcode it returns

it as a string so that's what we're setting up here is hey when you find the barcode send it to your delegate right and our delegate is going to be our coordinator so our coordinator is going to get that barcode and then our coordinator is going to be like thanks view controller and the coordinator is going to take that barcode and send it up to our Swift UI view okay that's the

big picture Okay so on our scanner VC we're going to need a couple properties here so let's do let capture session equal AV capture session and This Is Us capturing you know what's what's on the camera right so again keeping the super high level we're also going to need a preview layer and there's going to be of type AV preview video preview layer right it's going to be optional for

now because we we set this up when we set up our capture session so we don't have this value right away but what the preview layer is is kind of exactly what it sounds like it's what actually is displayed on the screen as you're moving your camera around like you see here on the screen and then next we'll need a weak VAR for our delegate I'll call this the scanner delegate

and that is of type scanner VC delegate and commonly you'll see this Force unwrap like that because we are going to pass this in when we create it but if we really want to be safe here we can not force and wrap it and we can make it part of our initializer so when we create our scanner VC it's going to be required to take in a delegate so let's actually create

that initializer now so uh init we'll say scanner delegit of type scanner VC delegate and we'll do self.scanner delegate equals scanner delegate so basically what we're saying here is when we

self.scanner delegate equals scanner delegate so basically what we're saying here is when we initialize this we're going to take in a scanner VC delegate you'll see we'll do that later and then once we initialize it we set our self.scanner delegate which is this to scanner delegate so now we we don't need to make that optional because we know we're going to have it when we init okay

now you see we're getting xcode yelling at us as required initializer in it with coder this is uh you can do this and just leave fatal air in there and I actually just like to put this on one line so real quick this is basically if you ever initialized a scanner VC the storyboard we're not going to do that obviously this is what we get fired off so you do need to have this in there

and then oh yeah I forgot to call the uh the superhero in our net so super dot init and then because we're initializing a view controller it does take in a nib nib in a bundle uh these are just both nil uh in our case but you have to have that when initializing a view controller it's the designated initializer on a view controller okay so what we have set up is our properties here our

initializer now the main function we're going to have on here is going to be uh private funk setup capture session so this is where we're going to basically do all the setup to get our camera actually you know looking for barcodes and you know our preview layer up and running this is again the this is the heart of the screen here and in this function there's a lot of like

checks to make sure you know we even have access to the camera make sure things are okay so you're going to see a lot of that uh you know in the beginning so first of all let's guard let video capture device equal AV capture device here dot default four in the media type here right you can

built into I mean whatever we just want for for all the the video here vid EO cool uh L so this is basically saying like hey do we have a device that can capture video and then else we're just going to return for now but this is where we would present an error because just like it's important to pass the barcode information well if things go wrong we want to pass the error as well so

we'll we'll have a whole separate video for that uh later in this section okay next let's say let video scroll up here a bit input AV capture device input there you go and by the way like what you're not seeing is I have all this code off to the side like I don't have all this AV Foundation stuff memorizing the camera yeah I've used the camera in a few different apps I'm familiar with it but like

I just want to set expectations right I don't have this memorized I'm editing out me like looking and reading right because people don't memorize like all their code so in case you're wondering like man how does he know all this stuff I don't so again don't think that you're you're lesser if you don't have all this like memorized just just a little caveat there so with video input we need

a do try catch block so we can say do and then we're going to try video input equals and we'll initialize an AV capture device input and it takes in a device and this is the device we just created up here if we had it right the the video capture device and then if that doesn't work we go ahead

and catch that here and this is again where we'll surface an error but for now we're just going to return again more error handling uh later so now again more checks so if capture session dot can add input we want to make sure we actually can get input from the device here and the input is again video input that we just created right up here and then okay so if we can add input let's

add the input so capture so again just a lot of checks uh not K net input add input and the input we're going to add is video input else not self so you just type in self else and again return but we're gonna we're gonna put an error in here later okay we're almost done with all of our our checks

here to make sure we even can use the camera all right last check here so say let metadata output now this is what actually gets scanned here equal AV capture meta data output and then here one last check oops I got to initialize that my bad and then okay back to our last check and this check

is similar to if we can add input we want to check to see if we can add output so if capture session dot can at output and then the output again is the metadata output we just put up there if that is true we're going to add it so capture session dot add output metadata output again AV Foundation is

very very confusing I'm not going to act like I I know it very very well I can use it I've used it before but if you're not understanding what I'm doing right now don't worry in fact I even debated on just not even doing this video and just giving you the view controller like hey just copy and paste this view controller but I thought some people might want to actually go through this so

again another caveat if you're lost right now don't worry this is a swift UI tutorial this is not an AV Foundation tutorial so now we want to start adjusting this metadata output so metadata output dot set meta we're basically setting the delegate here right set metadata objects delegate and it's going to be self and then the queue is going to be the main queue and that's dispatch

uh Q dot Main and we're getting an error because I did not capitalize data in metadata took me like a minute to find out what's going on here and that's not actually the reason I was getting an error we're not uh conforming to the delegate yet here so let's just so xcode stops yelling at me we'll get a little bit ahead of ourselves here extension on scanner VC and This Is Us conforming uh to the

delegate here so we want to conform to AV capture metadata output objects delegate it's a mouthful right but this is what we're just doing here right set metadata objects delegate well we need to conform to that and then do command B it'll yell at us we're not conforming to the delegate or not built succeeded I guess they're not uh required functions here so we'll come back and fill that

in later so next we want to do metadata output dot metadata object types right so now this is an array of basically types of barcodes that we want to scan so if I do dot you can see these are all the different types of code barcodes and all the different stuff you can scan right QR human body

that's interesting I guess but we want ean8 and Dot ean13 and this is just the the standard eight digit barcode or 13 digit barcode you see up on the screen so that's what we're doing that we're basically telling the camera hey look for these types of barcodes okay and back up a couple lines here right we're saying if we can add the output cool but if we can't this again surface the air

for now we're just going to return okay so that's our last like check to make sure everything's good so the last thing we need to do here uh well two more things we need to set up our preview layer based on all the checks we just did so we can actually show the camera and then we do input the

delegate method here to implement what we want to do when we find the barcode so here we can finally set our preview layer so preview layer equals AV capture uh video preview layer there it is right you initialize that you can see it takes in a session which is an AV capture session which is what we've created here with our capture session so we want to pass in the capture session that

we just set up and did all our checks on right so basically we set up our capture session make sure everything was good to go once it's good to go now we can set that to our preview layer now we can do preview layer Now preview layer isn't optional I'm going to force unwrap it here and I'll tell you why here and we'll do video gravity equals resize aspect fill basically what this is

saying is whatever view we create if on the design right we have this black Square that's kind of the structure of our view basically saying fill that view but keep your aspect ratio is what this is doing and back to the force unwrapping now again hotly debated topic I'll touch on why I'm doing it here we're literally setting preview layer right here and on the very next line we're using

it right so you know there's two camps I think it's okay to sometimes Force unwrap and this is an example of that situation uh there's other people in the camp that are like never Force unwrap you never know there's always this you know 0.001 Edge case that could happen they're not wrong it's fine um I just told you the camp I'm in if you're in the other Camp cool unwrap the optional no

big deal and then here we add the preview layer to review so we do view dot layer dot add sub layer kind of like view dot add sub view similar concept here and then the layer we want to add is our preview preview layer again Force unwrap that because we we have the value literally right there okay so now we have our preview layer set up with our capture session

uh the final thing we need to do is actually do capture session dot start running so this will actually start running the capture session so you can see the preview on the camera okay so that's our av Foundation code you know we just set up our capture session with a bunch of checks like do we even have access to video can it do all this stuff and if all that is good then we set up

our preview layer to show our capture session and basically start running the capture session super high level that's what that code is doing again don't worry if you were lost AV Foundation is uh trips up a lot of people okay so the last piece of the puzzle is what to do when we actually scan a barcode and again remember barcode has to be ean8 or ean13 right so when that happens what do we do

well here's where we tell our delegate which in this case is going to be our coordinator uh the barcode that we found and remember the coordinator is going to take that information and then pass it to Swift UI that's the whole flow here so the delegate method for that will do 5 bunk meta data and you can see it's this big long one here right did output metadata objects so what we get

back here that's key is our metadata objects this will be the barcodes that we scan here right we get an array of it and then from the connection is our av capture connection that we set up okay so cool so what we want is the first object in this array right we just want the very first one that

it found so let's set that up first so let's check to make sure we have it guard let object equal meta data objects again this is our array DOT first right again we just want to take the first one else and again we're going to return here we'll do the error messages later I know I'm a broken record okay we have our we want to make sure we have our objects that is the first

one in the array now we have to do another check on the object and we do guard let machine readable object equal object and then here's we have to cast it and and again I had to look this up I didn't I don't know this off the top of my head but it needs to be of type AV machine metadata machine readable codable like this it's a lot it's a mouthful right it's basically machine read

object here else and again we'll do the error stuff but for now just return okay so now we have the machine readable object but this has a string value attached to it and that's what we want right we're digging through the data to get what we want and we want this barcode string value that we're going to get here the guard let uh barcode equal machine readable

object dot stringvalue okay so make sure we have a string value else again return with the error okay and if we have that we just want to do delegate right this is the delegate that we set up I'm sorry scanner delegate dot did find and then the barcode we found was barcode okay again that was a lot of checks everywhere real quick hey do we have a metadata object in our

array cool grab that is it this machine readable code object cool moving on let's take that machine readable object and get the string value of it cool got it okay that string value let's send it to our delegate right so now whoever our delegate is right now at this moment nobody's our delegate we haven't set that up yet so right now if we ran this uh our scanner VC is just

like screaming into the void here's my barcode here's my barcode uh nobody nobody's listening that's what we're going to set up in the next video but that's what we just set up right now which is one side of the communication and here is US after we did all that setup finally telling our delegate what we found so now that we've told our delegate hey when we

found a barcode in the next video we're going to set up uh the structure for our errors so that we can also tell our delegate like hey we messed up somewhere along the line uh here's what happened in the last video we built our scanner VC you know setting up the capture session as you see here again if you're a little bit lost it's fine don't worry about it uh but just know that what

we set up is when we find a barcode we're now telling our delegate hey we found a barcode right so that's the successful case deleting my spacing here so now we're going to set up our the structure for our errors so that we can also pass up the errors when when things don't go right because that's just as important right especially when you're building a production app you know

strong error handling is a huge piece of it so up top we're going to create this here for now just to keep things here we'll kind of you know project organization later but let's create an enum called camera error and for now it'll have a raw value of a string because we're going to kind of attach our error messages here for now we're going to do more error stuff later that gets rid of this

um so the first case is you know we'll call it invalid device input equals and this will be the string raw value I'm only going to create two errors uh in reality you you may need to create an error type for each one of the different checks because you know proper error handling you want to tell the user like exactly what went wrong but just for the sake of time and instead

of having seven different error types I'm just going to keep it to two to keep them generalized but I do want to let you know that you know you can get very well you can and should get very specific with your error messages so case invalid scanned value right you know I like to tab these over okay so for now we're going to put these strings here something is wrong with the camera

we are unable to capture the input right and then here we'll just say like the value scanned is not valid this app scans ean-8 and ean-13 again those are the barcode types okay so I'm going to move

this over here I'm so anal that bothered me uh okay so those are our error types for right now so what we need to do is also now have a a delegate method here just like we did find that fires off uh when we successfully found a barcode now we need a protocol method here to fire off when

we got an error so I'm going to call this funk did surface and then call the parameter error and that takes in a camera error that we just created right up here so now at all these places right where we had just returned right because what happens when you don't surface an air here if video capture device you know this fails then nothing happens like it just fails silently and the user is left

like clueless like why isn't my camera showing up what's going on they have no idea so that's why you want to surface the errors uh you know just to let them know when your app doesn't work properly here's why so we're going to add this one line of code throughout here but again it's just delegate or I'm sorry scanner delegate dot did surface error and then the error we want to pass in is dot

invalid device input right again these are just the two generic types our capture device is messed up I'm actually gonna copy this so I don't have to type it out a bunch because here the same thing if the video input is wrong we're going to invalid device input if the Caps recession cannot add the input right instead of just returning we're going to surface the invalid device input and again I

know I'm a broken record but in reality these could probably be like different errors with different messages but again for the sake of time in Simplicity we're just going to do this okay and then we are going to change it up to invalid scan value down in the bottom here but that handles all of our like hey can we even capture the camera type checks that we were doing

um handles out with invalid device input so now in our delegate here right where we actually scanned it successfully but now we have to make sure it's the right type of data now we will do here scanner delegate Dot did surface air except we're going to pass in invalid scan value and you can see the power of putting your errors in an enum if you're not like familiar with that right instead of like

typing out the error message string or whatever I can just pass in invalid scan value and I get the autocomplete and all that good stuff so again we'll copy and paste this uh three times here one two and three so you notice we we surface the air like seven or eight times and we only did did find once and that's pretty typical when you're doing proper error handling right because

usually a lot of different things can go wrong but there's only like one right way to do things so uh it's a little skewed there but that's typically how it goes okay so now we have our scanner VC basically done again we have it set up so on a good case we yell into the void here's our barcode when things go wrong now we're yelling into the void hey things went wrong here's the

type of error it was so again what we need to set up now is someone to listen to our view controller that's yelling out all this information and now that is going to be our coordinator our UAV controller representable that has a coordinator that's that middle person in between our UI kit view controller and our Swift UI view so let's go set up our coordinator too I listen to this thing

now we get to get back to Swift UI and start building our coordinator in our UI view controller representable right we're we're almost done with all the AV Foundation stuff I know that may have been rough but I did forget two things in the last video uh because I got distracted so uh right we we created our setup capture session function but we never called it so after our Niche we want some

view lifecycle methods here so if you did load super Dot View did load here and then we want to call set up capture session right because if you don't call your functions uh they don't run uh and then the second thing we want to do is uh set up our preview layer after the view did lay out sub views so again more review lifecycle here uh view did layout sub views super Dot View

did layout sub views and then here's where we want to set our our preview layer preview layer dot frame right we want to set the size of it equals view dot layer dot bounds right so but this is optional and we want to surface an error if this doesn't work correctly right so well

we're just going to unwrap that optional guard let preview layer equals preview layer else and again scanner delegate dot did surface air and then this will be invalid device input and then uh return right and then now this no longer needs to be optional so again what's going to happen here is if we don't have a preview layer yet we'll return this error and this will actually fire

off when you try to run your camera on the simulator because again there's no camera on the simulator and then we'll go ahead and make the preview layer equal to the layers bounds the size that we declared okay so that was the two things I forgot uh in the last video now we are done with this view controller uh and now we can go to create our scanner view which is

going to be our uiv controller representable so to do that click on Barcode Scanner command n new Swift UI view hit next let's call this scanner View and we'll make this small now if you remember me describing this right a normal view which is what we have right now has a body that returns some view in this case it's text but remember if we conform to UI view controller

representable here now the body that normally would be returned like this is still a view that we can use in Swift UI but the body that we would return is replaced with the view controller uh that we can make so if you do command B what it's going to say is we're not conforming to that protocol right remember the two stubs make view controller and update view controller however

xcode has you do something first right you're going to say oh add protocol stubs we're just going to give you this this type Alias but this can be a stepping stone right because the view controller type we're going to use is scanner VC so now if you do command B now it's going to give you the same thing does not conform but now it's going to give us the the proper protocol stubs

and it figured it out because we told the view controller type it was a scanner VC so here we go and then we're not going to use this anymore so we can delete that that type Alias but we did get our make view controller and our update view controller with the scanner VC right now if you have a Keen Eye and you remember what we did last time on the Safari review controller that

we're going to go back and fix with um right we had a much longer thing here for context right we had actually UI view controller representable context right and then that took in a uh scanner View right that's what we had last time now uh what we got when we did the autocomplete there

was just context so that's nice and neat that's nice and clean but let's see what context is so if you click in it jump to definition context is just a type Alias for that UI view controller representable context with self in it right so that we put in scannerview there last time context is just a type Alias for that so it makes makes it nice and neat quick rant on type aliases I have a

love-hate relationship with them uh oftentimes I feel they just add an extra layer of complexity to try to figure stuff out a lot of people use them for like closures me I would rather see like the definition of the closure right there rather than like having a type Alias that just says like closure and then I got to go look up what it is like it has an extra step however in

this case I like it right because it just removes all that boilerplate because this is always going to be that UAV controller representable context with you know scanner view in it so anyway sorry for that type Alias rant but we're going to keep this context now because it's the same thing there okay so just like before our update view controller is just an empty implementation

um you know again if you were doing updates to the view controller you could you know that's where you would do it so right now we need to return a scanner VC but remember we set up an initializer right on our scanner VC we initialize it with a scanner delegate and remember we want the delegate of our scanner VC to be our coordinator which we're going to set up here in a second so

that's going to be context which remember context is again that the scan review essentially uh Dot and you see it as a coordinator on it now it's not going to work because we don't have the coordinator set up yet but that's what it's going to be so let's let's set up that coordinator so down here below our update we're going to do final class and just call it coordinator now you

may have never done this before right where you're putting a class inside a struct right that seems weird you could Define this outside of it but if you had multiple coordinators in your app which if you're building a larger app you're probably gonna have to drop down to UI kit a couple times uh so you may have to like name these specifically like Safari coordinator camera coordinator and that

just adds a confusion if you just put it here on the scanner view you just have it built in on there you can always call it coordinator you don't have to have like you know proper naming so our coordinator is an NS object and then it needs to conform to remember I said our coordinator is basically the delegate of our scanner VC right so that needs to conform to scanner VC delegate

and remember in this in this path that we saw here right our UI kit talks to the coordinator coordinator talks to Swift UI so we're setting up that first part of the communication there where our coordinator is listening to our scanner VC that's what the scanner VC delegate is now if you look here scanner review.coordinator does not conform to the protocol so hit your fix-its and

you're going to get your protocol stubs which they are should look familiar right we got did find and did surface air right so this is the UI kit telling our coordinator hey I found the barcode here it is do with it what you want but what the coordinator is going to do is tell our Swift UI view right again it's like a two-step process so for right now we're just going to print bar code

and then for did surface air we're going to print uh error dot raw this is why we put the raw value on our camera error if I go back to our scanner VC the raw value here is this string right we're going to replace that in the last video when we properly do our errors but to test this communication I just want to make sure we have the value before we work on the next step on

passing it to the Swift UI view okay to review that real quick we created our coordinator here we made it conform to scanner VC delegate and we implemented our delegate methods and then we're doing something temporarily with the info we get that is the basic setup we're you know not 100 done yet but xcode is still yelling at us saying scannerview does not conform to protocol

uiv controller representable wait a minute I thought we just did that right it was only these two functions that needed to conform right make UI and update UI view controller well when you have a coordinator you have to do another similar function called make coordinator right so hit that and you'll see it'll add it in there make coordinator I'm very particular about

the order so right I think make coordinator is kind of kind of come down here last but anyway uh this gets called automatically just like make UI view controller gets called automatically right when a scanner view gets built it's automatically going to call make view controller make coordinator uh so we need to basically return a coordinator here and what coordinator are we

going to return well that's this one down here so let's initialize a new uh coordinator okay so now our coordinator is officially listening to our scanner VC right that's step one in the process UI kit tell the coordinator okay I think we have that set up let's test it first I'm going to test on the simulator because we should get an error because the simulator doesn't

have a camera so we should see a printout of the air.raw value and then I'll test it on a device and we should be able to print a barcode when I scan something so let me actually run this see on the iPhone 12 Pro we'll run it and then we should get an error print out in our console

no and we didn't you want to know why see if you can guess why I'll give you two seconds one two all right because Sean's a dumb that's why again these silly mistakes happen all the time so here's why I didn't get the printout right because if I go back to my Barcode Scanner view I just still have just a regular rectangle right don't even have my scanner view so that

would help right so instead of a rectangle here we're going to have our scanner View again that the frame is everything is the same that's what's nice about setting up like the dummy structure is all I had to do was replace rectangle with scanner view good to go so now when we run it it's going to initialize the scanner view here which again uh in our scanner view when

it initializes it's going to call make UI view controller it's going to call make coordinator it's going to set up all the delegates and then uh I should get an error because it's going to try to set up the camera but because I'm on the simulator it shouldn't work in theory there we go okay so I got the the error down here in the console you can see it printed

out a bunch like seven times uh here's why and I'm interested to get your feedback on this I would like to hear because I don't have a great solution so if I go to my scanner VC here this error that's printing out is in this uh is in my view did layout sub views right this is the one that's getting uh fired off and that's because if you did layout sub views gets gets ran a bunch

of times now here's why I kept this in here is because later in the error alerts it it doesn't affect anything so I think it's fine because it's really the only way to surface an error if we wanted to actually surface an error I mean the other option would be to have it fail silently um which I don't really want to do so anyway I'd be interested in your your feedback like what do

you think of this is having this error message fire off seven times because if you did layout sub views like just that's how many times it gets called um you know I'm sure you could run some crazy check logic to make sure it only runs once but I don't know I feel like this is not hurting anything it's not doing anything so I don't know but I would love your thoughts on that if you if

you do that's not what this course is about but a little side note anyway okay so back to our Barcode Scanner view like I said uh we did we did the air show up oh no it didn't show up because we haven't set up the alerts yet getting ahead of myself um but what you saw happen was in our

scanner view yes it is working did surface fire it off and our scanner view is printing this so step one of that communication chain working our coordinator has the information it needs actually I just tested the error let me actually run this on device and see if it can actually get a barcode all right so now I'm going to run this on my iPhone 12 Pro here weird Flex just got it

um and then the barcode I'm going to scan is the iPhone 12 Pro box here and I'll put up like a little picture in picture because I can't just like throw it up like I can the simulator okay so you see the first thing that pops up is the camera permissions right remember remember setting that up a couple videos ago so I hit ok now you see my preview layer a little little sneak peek in

my camera setup and lights and here's the code so okay if I scan the barcode of you see here my Apple box see if this works here right cool now you can see it printed out a bunch right and then we got we did get an error the scan value is not valid because it must have picked something else

up uh but I want to point something out right it picked up a number like a ton of times like it's constantly scanning uh there's two two trains of thought here right so if I if I go back let me stop running this here and we'll go back to some code so if I go back to my scanner VC here you'll you'll notice we can start capture session well we can also stop the capture session

right so I guess it depends on the functionality of your Barcode Scanner this is a bit beyond the course but I'm just letting you know like how you should think about it so you can imagine there are some use cases where you would want to continuously scan right like just scan and display the barcode right that way you could scan a bunch of different barcodes at once or there

could be a case where like as soon as you detect one barcode you want to stop scanning because maybe you want to check that barcode against the database to see if you know it exists in your database so there's two kind of you know use cases right I can see Arguments for both um the reason why I kept it running is because if you do stop and I'll show you here we can go ahead

and do that just like you can call start running you can call stop running down here I can call capture session dot stop running and this will stop it as soon as I like detect a barcode here if you're having issues scanning a barcode here's what you can do real quick go to Safari see a barcode example already in Google and then you can just see it stopped right away so it picked up the

barcode now let's see what happened here right so it printed out the barcode here in the console and then stop running got captured now the reason I didn't do this is because they'll like restart it we would have to implement like a restart button and do more UI and I felt that was going too far down the rabbit hole of nothing to do with swift UI and UAV controller representable so that's why

I just kept it running but I did want to show you that you can stop the capture session if you do want to like take this barcode scanner and like maybe build something upon it or implement it into an app or something but for right now you can see back in our scanner view that first step of the communication is working we're able to get the error raw value we're able to get the barcode

now we need to set up the coordinator so it sends that message to our Barcode Scanner view so that we can display the barcode properly on the screen or any errors if necessary we're going to do that in the next video all right we left off last video with UI kit properly communicating with our coordinator now we're going to take that information from our coordinator and pass it

to our scanner view so to do that we're going to use State variables and bindings this is where it may get a little familiar this is now kind of the stuff we've done already but it's always good to review and for you to see the whole process now at first we're going to do this all in the barcode scanner view but really this type of stuff you know should be in the The View model we're going

to implement that later but I want to walk you through this way and then refactor I think you'll get a better understanding that way so we need a variable here right our state private VAR called scanned code right this is what it is and it is a string and actually let's just initialize it with uh an empty string so what you'll notice if I just left it like that and this is kind of a cork which

not a quirk I guess this is how it's designed but if I just leave it there now when I create a barcode scanner view I have to pass in a value for scan code like when I initialize it like here in our app right I would have to pass in some value for scan code so if you give it a default

value you don't you don't have to initialize it um with one and in our case the empty string is fine you'll see how we check against that so let's work on the the barcode part first because the error is a little more complex because we're setting up like the our air alert structure so let's just keep this simple uh with the scan code first so again to review state variables real quick

basically State uh whenever scan code changes the view will get updated right so instead of our text saying not yet scanned we want that to be based on the scan code so we say scanned code dot is empty so all strings have this is empty Boolean to check to see if it's an empty string which ours is right

now so if is empty is true we're going to say not yet scanned right and if as empty is false we're going to say scanned code and similarly in the foreground color we can do scan code.is empty if it is empty we want it to be dot red if it's not empty we want it to be dot green right we want

not yet scanned to be in red and when we scan a code successfully we want that number to be in green and again I'm kind of spelling things out the long way we're going to refactor this better in the view model later but I think spelling it out like this again is is easier to understand okay so now that our UI is going to update you know whenever scan code changes and it's going

to update properly we need to basically change our scan code and we want to change our scan code whenever you know we scan it right but right now our Barcode Scanner view doesn't have a way to get that information right because our coordinator has that information but our UI here our bar scanner view doesn't so in our scanner view we want to create a binding to scan code right

remember what a binding is is whenever we change that binding in the scanner view it will update the one here in our Barcode Scanner view I know those are similarly named maybe we should have been better about that so anyway in the scanner view right we want to create a binding at binding VAR and this is scanned code and that is a string so I do command B to make sure we get it here okay

build failed oh yeah we don't have a parameter right so here right in our Barcode Scanner view now that we've put that binding there we need to initialize our scanner view with a scan code and that is going to be a binding to this scanned code up here remember that's what that dollar sign is a dollar sign is how you make those bindings so again whenever we change this scan code variable

in our scanner view it's bound to this scan code and that's going to update and then when this updates our view is going to get redrawn and updated accordingly based on our ternary operators here you know when we have a scan code and when we don't okay so if I do command B that error should go away we're still not done why because these previews on our scanner view remember I told you

previews are always going to get you and again for bindings in order for just for your previews you can do dot constant and then you give it a value one two three four five six that's kind of like a random barcode view but that's again just to get the the preview initializer done so now we have a binding to scan code so so here in our scanner view we just need to update the scan code

and that'll trigger all of our changes so you may think cool well in my delegate method where I get the barcode right did find I have a barcode uh why don't I just do scanned code equals bar code cool good to go wrong now remember like I said our coordinator needs to pass information to our scanner view but right now if you look at our final class it doesn't know about our scanner view

it doesn't know like there's no connection there so we can do here is private let scanner View and that is of type scanner view right so we're giving it a property of a scanner view so we can make that connection okay getting a bunch of Errors that's fine let's comment this out to avoid confusion we'll come back to you later what this is saying is like now now we can't initialize

a coordinator with nothing right because we have to give scan review a value so what we do here is coordinator scanner View right and that takes the type of scanner view but we can pass in self right could because on here self is the scanner view right so this scanner view when we create our coordinator we're saying that hey I am your scanner view essentially

and I forgot the initializer sorry for the confusion there so we can do init and then initialize with the scanner View and that scanner view is of type scanner View and this is just like a normal UI kit type initializer so you would do self Dot scanner view equals scanner View and again to explain this real quick when we initialize It Whatever scanner

view we pass in here we're going to set that equal to ourself.scannerview which again is this scanner view up here when I set a scanner view a thousand times there do command B we should be good to go so again when we create our coordinator inmate coordinator we're passing in self as the scanner view which again is the scanner View and then here we're setting that scanner view equal to that so

that is how we made the connection between our coordinator and our scanner view so now instead of just doing scan code.barcode we need to do scannerview.scan code.barcode right because our coordinator doesn't have a property called scanned code right our scanner view has a property called

scan code and again we pass in that scanner view here so we can use it there and then to finish off this thread right so now we're setting the scannerviews.scan code equal to barcode when we found it right remember the UI kit component talks to our coordinator says hey I did find a barcode so this is our coordinator saying great I got your barcode now let me tell the scanner view what that

barcode is so This Is Us telling the scanner view what the barcode is and then here our scanner view because it has a binding right so our scanner code scan code changes but this is a binding to our Barcode Scanner views scan code right so when that changes this is going to change right we're just pulling on the thread here and when this changes now our up our UI is going to redraw and update

accordingly right because scan code will no longer be empty ideally right we send in a barcode so now it's going to change to the scan code and the color is going to change to Green in theory Let's uh let's test this out all right so I'm going to run it on my device throw up the picture in

picture so you can see my device so let's open up as far here for our example barcodes and there you go you can see as it's scanning let's try and scan like a different one to see the barcode change okay so cool you can see our numbers changing as I'm scanning different barcodes right so nice our UI is all connected uh as you can see our numbers are changing the color is green when we scanned it

and that wraps up the connection between you know UI kit to the coordinator to the scanner view uh that is coordinators in a nutshell we're gonna go through that process real quick one more time with our error alerts uh just to kind of give you practice and drive the point home and then we're going to refactor in Project organization into an mvvm and organize our project to finish

off this app we left off last video getting the whole communication pattern with coordinators done for our scan barcode well now we want to do that again with alerts but first we want to kind of set up the the structure of our alerts uh you'll see why in a second because there's kind of two ways to do alerts one's pretty basic and one is more involved and the more involved

one is actually what you're probably going to use in like real apps and you'll see why so let's start with the basic alert here and we'll just do this on a quick button tap so after our text add a button this is just temporary we're not going to keep this button here so label this will be a text I know there's a quicker way but I don't care I'm just doing this temporarily

real quick tap me right and on this we want to show an alert and again whenever you want to update your UI you need a state variable here so you can do at State uh private VAR is showing alert and that can equal false at first so in our button tab we just want to make this true is showing alert equals true so that is the the trigger to show our alert again this

is the super basic way this is kind of a side note I'm showing you we're going to build the more involved way but I want you to know this because sometimes you may just need this simple way so now we want to put the alert on our vstack here we can do dot alert and then you see it's item and content or is presented so the more involved

one involves an item we'll do that later right now we just want is presented and the is presented we want is The Binding to is showing alert and in the content we want to show capital A to initialize an alert and you can do right title test message this is a test dismiss button we'll do dot default and

you see it takes in a text so we'll do text of just okay okay so just a super dead simple alert and maybe you can start to see what's going to happen here as soon as I tap tap me is showing alert is going to flip the true and because this alert is kind of watching is showing alert

it's going to show when that gets flipped and I forgot this is not just a string I need to do text used to kind of the UI Gateway this is the Swift UI I got to wrap it in a text so there we go okay so that should be the default alert I'm going to run this on the simulator because it's a pain to

show you my phone with the camera uh so let's run it on the iPhone 12 Pro and then you'll see the alert pop up well I think we'll get an alert for the camera not working which I think we tested before nope that's a lie we haven't connected that yet that's what we're doing this video getting a

little mixed up okay so you see our tap me button down here I'm gonna move this over here so I'm going to do tap me bam there's the test alert test this is a test and then when you hit OK it automatically dismisses you don't have to like set up the dismissal so again tap me alert bam that is the super basic way just on an event you do is presented based on that state variable cool

when you do it based on an item it triggers when that item changes and we'll we'll do that here so let's get rid of this alert for now because we're gonna set some stuff up let's get rid of this button told you that was just temporary and then let's get rid of our is showing alert uh variable

however we are going to need an alert item so we can do at State private VAR alert item and that is going to be of type alert item that we don't have yet let's create that I'm going to create that right here for now just so it's all very visual for you you can see what's going on we're

going to come back and like obviously organize this so we can make a struct called alert item and give that the properties right the properties we need on alert item as you well I deleted it but it was like a title a message and a dismiss button so we can do let title

that is a string let message also a string and then let this Miss button and that is going to be an alert dot button and basically I'm just recreating that autocomplete that you saw before uh on the alert so that's our alert item so now this is of type uh alert item

there we go and it's going to be optional because we don't have an alert item yet we're not sure which one it is and we're going to build our alert item based on whatever error type we pass in Back to the scanner VC remember we had our camera error well that's what we're going to use to determine uh what information goes in our alert item and here we're going to create another small

struct again this will go in its own file later struct called alert context and this is another kind of helper shortcut you'll see how we use it here very quickly but this is where we basically create our alert items static let invalid device input equal is going to be an alert item that were

we just created so alert item parentheses and you see I get a title message string so the title we can say invalid device in put and then bring our parameters down here on the on the same level message again we're just going to copy and paste the message that we already typed from our our scanner VC here right in our remember I said we're going to come back in and get rid of these

raw value strings it's because we're using it here in our alert context and if you're a little confused not following along I think you'll this will all come together in the end and I'll come back and explain it so if you're not quite following along it's all it's all good so there's our message and then again our button we want to have dot default with a label of text

uh okay that's what we want and whatever you want your your button to say you can you can say that so let's copy and paste this because we have two types of alerts right we have our invalid scan type so let's do that say invalid dot scanned and be careful of uh copy paste errors they'll get you

every time so here in the title we can change this to invalid scan type and then again back in our scanner VC we'll copy and paste that message oops in our Barcode Scanner View here's the message and then we want our button to be okay so what this is an example of is usually in a bigger project

you know you're going to have tons of alerts right Network calls different types of Errors there's so many different errors in a project so I usually have an alert context file that has like a ton of these right we're only using two for this example but you'll see how this makes it very very easy to call certain alerts again I'll put it all together and we'll do the review but again what's happening

is we're creating individual alert items based on uh our error here so now we can go back to scanner VC let's get rid of this just for cleanliness here we no longer need a raw value of a string and we're probably going to get an error because it's expecting to read that raw value do command B build failed yep that was expected click on the error yep camera has no raw value so

we'll just for now uh print the empty string just so we don't get an error we're going to come back and obviously Implement that here in a second so now back to our Barcode Scanner view which is holding our alerts uh that's the setup so now what I want to do in my Barcode Scanner view again create that alert again just like we did last time but instead of the is presented we're

going to use the item and the item is going to be a binding to our uh alert item property here on our Barcode Scanner View now what you'll notice here is it says binding identifiable so that means this has to be identifiable so if we go back to our alert item let's conform the alert item to identifiable and if you remember when you conform to identifiable

what you need to do you need to let ID equals uid to give it an ID something to identify by so now that alert item conforms identifiable we can create The Binding here binding alert item and then again the autocomplete will get you sometimes so the alert item we want to do Open Bracket alert

item in okay so now here's we want to build that alert that we built uh previously so we do capital A for alert and then initialize it and again we want to title message dismiss button right now you can kind of see why I structured my alert item title message dismiss button all right so title is going to be the alert item that we get back here alert uh item dot title

same thing alert item Dot message and we can you know for for cleanliness here let's do this and then alert item dot dismiss button okay do command B hopefully we don't have any more errors we do have errors again I keep forgetting to wrap this in the text text there we go now we're good okay so again what's going on here is our alert is waiting to see what

alert item it gets and when it gets an alert item right we have it here now we're setting the alerts uh title message and button to whatever alert item we passed in and if you look up here the two alert items we created in our alert context are the invalid device input alert and then the invalid scan type alert and a quick note about alerts the reason why you have to do this is

because you can't have more than one alert on an item right I can't I can't like do dot alert and create another one you know for my different cases that it's not going to work you have to have one so that's why you create one alert and then pass in variable context into like what the alert is so now let's actually use our alert context right how are we going to pass our Barcode Scanner view

like we have to we have to update this alert item right so remember our communication path right UI kit to coordinator to scan review well let's go to our coordinator because our coordinator has our alert information right here right we have the air type that's all we need we just need to know what error type it is but again we have to communicate from the coordinator to the scanner View

you know what's going on so here in our scanner view let's create a binding and again I'm going to run through this again and hopefully it'll make sense if you're a little lost um so this coordinator thing is tricky the first couple times you do it but after that you you get the hang of it so we want an alert item and again that is a type alert item that is optional command

B we're going to get an error because we need to now initialize our scanner view with an alert item whereas our scanner view initialized on our main Barcode Scanner view here it is scanner view remember we passed in the The Binding to the scan code now we need to pass in The Binding to the alert item so when we update the alert item in the coordinator this alert item gets updated you're

following this trend here when this alert item gets updated this alert triggers and and shows the proper alert that's kind of the path here again we'll go over that once everything's all built so missing parameter go ahead hit the fix it it'll fill that in for you so I need a binding to an alert item so getting a dollar sign to binding alert item okay so now I'm passing that

binding down to my scanner View right so now I need to update this alert item so the whole chain triggers off here well I'm going to update that in my coordinator right remember my coordinator was listening to the UI kit my UI kit uh camera view is saying here's the error so now my coordinator needs to pass that error to the scanner View so here we're just going to switch off the air type

switch error right that's what we get and on Case Case dot invalid device input we want to do well let's put in the two cases first right case dot invalid scanned value right so when it's in value device input we want to update the alert item properly right because that's what's going to

trigger the whole chain of events now here's where our alert context comes in we can do alert item I'm sorry not just alert item remember scannerview dot alert item I forget that a lot too so if you're forgetting that and remember that that scanner view is the the scanner view we had to pass in and put to our coordinator so it knew which scanner view to update now here's where the

the nice alert context comes in we can do alert context dot invalid device input right so the alternative to that well let me finish off here scannerview.alertitem equals alert context dot invalid scan type so the alternative here is to Define our alert here well you saw if I go back to

my scanner view like you saw how messy this alert code is right we want to get that abstracted away in its own file which it will be next next video but back to our scanner view like it's nice and neat here right so did surface air is going to come up all we're passing up is the enum case right I'm either passing up invalid device input or invalid scan value here in my coordinator I

know that okay cool when it's invalid device input I'm going to tell my scannerview's alert item hey use this alert item which is the invalid device input alert item again that we created right here so it has all that value it has the title The Message the dismiss button so back to the scanner view again this updates our scanner views binding to alert item which

again is bound to this alert item in our Barcode Scanner view so this is going to update when that whole communication pattern fires off when this updates this is going to trigger and this is going to update with the proper uh alert so now when I run this and I think I've tried to test this three times now now when I run this on the simulator well okay what's the error okay previews told

you previews are going to get you every time and when you update stuff and they're kind of like meaningless like our scanner view doesn't even have a preview in fact get out of here so uh you can see my frustration with previews sometimes so now let's run this on the simulator because our simulator doesn't have a camera we should get an error message uh pops up there you

go invalid device input something is wrong with the camera we're unable to right because we're on a simulator so now you can see our error is propagating from UI kit to the coordinator from the coordinator all the way up you know through our bindings to the scanner view to the barcode scanner view to properly update our UI so I know that's a long chain of communication but

how do you feel about coordinators again think of a coordinator as the the middle relayer the translator between UI kit and your Swift UI views right the UI kit view controller communicates with the coordinator via delegates and the coordinator communicates with swift UI just like a little middle person uh if you will now this can be a tricky topic I get it so if you

have questions uh definitely leave comments if you have questions about AV foundation in the camera look it up I'm not going to act like I'm a pro um so kind of save those questions uh keep it to the coordinators in the passing of the data but in the next video we're going to implement our our view models for this and clean up our project organization and do any last little bit of review

we left off last video with our project working hopefully you have a little bit of a feel for coordinators uh now we're going to refactor into mvvm and organize our project so first things first on our Barcode Scanner view again this alert stuff let's get it out of here in Barcode Scanner do command n for a new file Swift file next I always just call this alert and I usually

keep these together again organization highly subjective um but I don't I don't separate out my like alert item in my alert context into that import Swift UI here because it I don't know I think I find it more confusing to keep these separate because really this is all this is what gets long in this file is like you may have like 30 different alert contacts potentially right

in a big app so that gets kind of long but I just like to keep these all in the same file um okay so that is our alert that cleaned up our Barcode Scanner a bit let's clean up some spacing all right so now let's create our view model because again I like to have my My Views here be as dumb as possible like hey just tell me what the show and I'll show it right like

I don't need to know you know this kind of stuff so I like to put this in the view model so again Barcode Scanner do command n new Swift file hit next and then bar code scanner View and then just model at the end create cool here we go again import Swift UI is a final class

Barcode Scanner view model and here's the key here I know there's only like the second time I believe we're doing this um but we're going to get a lot of practice with this in the final app but again this is an observable uh object all your view models should be observable object there so what we want to do and our xcode is going to break for a little bit here is we basically want

to get these two pieces of data out of our view and into our view model right so I cut there I'm going to paste here except in the view model you don't use state or private you do published right because this remember the view model is like uh you know broadcasting its changes and you have to

set something up to listen to those changes right so publish means we're going to broadcast our changes here so we definitely want to uh broadcast our changes to scan code right because that's updating and then also our changes to alert item so back in our Barcode Scanner view right xcode is yelling at us because we moved our alert item in our scan code but let's create our view model

variable here our property now we're going to do at State object for this one and it's going to be VAR view model and we're going to initialize a new one that's the key here I know I said this before and I'll say it again bar code scanner view model and we are initializing a new one so super high level what to know we're gonna we're gonna do a deep dive into State object observed

object in the review section and we're gonna get more practice with it but again the key thing to remember if you're initializing a new view model right here that's what these two parentheses are we're creating a new one you want to use State object if you are passing in a view model from like a previous screen right because maybe your viewmodel relies on data from a previous screen

and when you create your Barcode Scanner you need to inject in a viewmodel with that previous data right so in that circumstance you want to use observed object we'll have some examples of that down the road but that's the key thing to remember creating a new view model State object passing one in observed object and again State object is brand new in iOS 14. okay so now that

I have my view model let's do a command B here now my scanned code right here is on my view model so I just do view model dot scan code same thing here view model dot scan code same thing here viewmodel dot scan code again I lost my syntax highlighting we'll do a command B here and again my alert item

just put viewmodel in front of it because we moved it over there so your command B failed okay we have alert items and scan codes over here as well we're going to clean this up too um but I want to do it one step at a time and again let's move our parameters kind of you know down to the next line

uh view model dot scan code command B cool everything good to go and if that was a little fast for you all we did was anywhere there was a scan code we just put a view model in front of it right because now that's on on The View model same thing anything anywhere there was an alert item we just put viewmodel in front of it okay let's run this to make sure our errors are propagating

properly I'm just doing it on the simulator cool errors are still working barcodes are still going to be working and I'm testing on simulator because it's a pain to like actually show it on device but hopefully you're testing this on the device as well so if we go into review model it's set up it's pretty basic we can improve this even more and again I like to have my my stuff clean and

easily readable I find this kind of stuff like not super readable right I have viewmodel.scanco.is

empty if it is cool our text is going to be not yet scanned if it's not it's viewmodel.scan code

now that's not terribly difficult to read but if all this kind of stuff is just super littered throughout your code I don't know it does make things complicated I don't know why I highlighted this that's that's got to be there but I was talking about like this kind of stuff right so we can create properties on our view model to to you know extract this logic and put it onto our

view model in fact I'm going to copy that because we're going to need that here so Barcode Scanner view model we can start creating some computed properties here right I can do VAR status text and that is going to be a string and then here we want to compute that and that's what it's going to that's how we're going to figure it out except we no longer have to have a view model

in front of it because we're on our view model right just use the scan code so now anytime I do like viewmodel.status text it's going to check is my scan code empty if it is cool give me not yet

like viewmodel.status text it's going to check is my scan code empty if it is cool give me not yet scanned if it's not give me scan code it's going to give me the proper data all we're doing here is moving that logic out of our view and into our view model to clean things up and you'll you'll see how it does one thing you see I didn't normally you're probably used to doing like return

that well in Swift 5.1 if you only have one line that returns you can omit the return um I'm not sure how I feel about that yet I'm slowly getting used to it at first it really threw me off like I didn't see the return I didn't think it returned something so if it's throwing you off and you're not used to it don't worry I did too you can put it in there

if you want but you don't have to have it so we're gonna do something similar so VAR status text color is going to be of type color and same thing right let's go go back to our Barcode Scanner view literally just copy this logic and paste it here but again we can delete the view model because we don't need that do a command B cool so now we

have variables you know viewmodel.status text viewmodel.status text color and it's going to do that logic uh here for us so again you can see how this is going to clean up our view here right instead of having all this logic in my text I can just do view model dot status text right nice and clean neat I like it same thing here you know even though this is not crazy logic I get it it's

pretty simple um but I just I just think this is much neater much easier to read like what's going on so to recap that like the only property on our Barcode Scanner view is our view model right and then any logic we have here if I click on our view model right our scan code our alert item you know some some helper method or helper properties right to get you know the logic in there for our

text and our text color like move that to the view model get that out of your view at least that's my opinion I like my view to be as simple as clean and as dumb as possible I find that just easier to understand when it's like that and I'm not going to refactor this text you could you can

make this like you can make a thing called status text I'm sorry A View right and refactor this out that way that just says status text maybe that's a nice little challenge you can do real quick I'm not going to do that and the reason being is I'm not like reusing it maybe I'm a little lazy I

don't know maybe you can you can just try it if you want but we're going to move on to project organization right start moving some of these files around and again this will be a little bit repetitive but I want to show you how I do it so again new new group for folders call this screens and again this is what I put in well in the folder I'm sorry new group call this bar code

scanner and then this is where I'll put in my my Barcode Scanner View and then my scanner view model and I usually put the viewmodel on top I'll make this bigger so you can see it I usually put the view model on top I don't know that's personal preference okay but now I have my Barcode Scanner that's the only screen so again on Barcode Scanner new group create kind

of this parent folder called views inside views a new group called UI kit components and again in here we're going to put in our scanner VC and our scanner View and again I like to keep the UI kit components segregated so you know eventually Swift UI is going to get a camera view and then that way I know exactly when I need to go in and replace right it's all in one

folder so the only thing left is like our app stuff I usually leave that out and then alert I usually do a folder new group called utilities you got to be careful with these utilities folders because these can end up being just like a Dumping Ground for like a lot of different stuff so if you do find yourself having like a lot of different utilities you know for example

like extensions other helper things like maybe create individual folders for those um just be organized don't have your utilities be a catch-off for everything just add folders to be organized so again that's my my project organization how I do that we've refactored into mvvm we've talked about coordinators again if you have any questions or comments concerns leave it in the comments or

you know hop in slack have a conversation there happy to help out but that wraps up this app the next app we're going to do is the big one it's the it's the final app that brings all this together we're gonna add a lot more stuff networking into the mix so these other apps have been you know five six seven videos kind of short next one's gonna be a lot longer so strap in

over the next 20 or so videos we're going to build this simple appetizer ordering app right where you can download a list of appetizers that you see here that's going to be our Network call we're going to get practice with that and implementing mvvm with our Network calls passing all that stuff uh but then you can tap on an item see the detail screen you can see with our match geometry effect

animation see the details about the item add it to our order and then go back to shopping for more if we want and then we have a very basic account screen that you see here I wanted to get practice using forms because a form like this whether it's an account screen a setting screen is quite common so I definitely wanted to get practice with forms and then the order screen that you see here

helps us manage an object like our order right because our order can be accessed from our our list screen and our order screen if we want to add or delete so managing that object you know in the environment of our entire app so even though that looks relatively simple on the surface like I said it's going to be at least 20 videos I'm not sure exactly how many quite yet but it can get pretty

uh in depth and on that note while we're building this I like I know you're going to want to be like oh man I wish we would keep go going and build this out further and build out this functionality build out that functionality and I hear you but you have to keep in mind if we went down all those rabbit holes built this out to be fully functional with like a fully functional backend database all

that stuff like like that's an entire separate course right it's already going to be 20 plus videos like if I did all that we'd be talking 50 60 more videos and I'd have to charge a hell of a lot more for this course it'd be super long so again this is Swift UI fundamentals we're keeping it simple so I want to put out that disclaimer before we start building this because again I know

the engineers and us the developers we're going to want to build it out more so uh just a quick disclaimer on that but like I said we are going to spend about 20 plus videos building out a nice foundation and The Core Concepts that you need to understand to build this app out further should you choose to challenge yourself and take this to the next level but remember this is a foundational

course so I'm trying to keep things as simple and as digest testable as possible I will have plenty of future courses where we do go very in depth on this you know more advanced courses okay with the app overview and disclaimers out of the way let's actually start building this thing in this video we're going to set up the basic tab bar structure of the app that you see pictured here so xcode

create new xcode project again it's an app hit next I'm going to call this appetizers right team whatever interface Swift UI lifecycle Swift UI app we're going to explain that in the next video we've kind of glossed over that until now well now's when we explain it and then language Swift of course next save it wherever you want save it to my desktop and as usual hold option click the

green plus there get rid of my right pane uh oh it is what's on Sean's iPhone 12 Pro get it to the simulator iPhone 12 Pro hit resume drag this over again that's just my usual routine there so first up we're going to rename this with the handy dandy renaming technique right click on it right

Factor rename uh let's call this the appetizer tab view hit return there we go so again this is we're going to return to tab view so you can imagine uh we're going to want a tab view I shouldn't have said you can imagine we haven't done this before why would you know that so it's as simple as that

though tab view we're going to put our text in here for now that's not what we want though I just put it in there so xcode stops yelling at us what we want in our tab view is to actually show three different screens right if I pull up the design again you see we have our Home tab our account Tab

and our orders tab so we're going to need those three screens so I'm going to create those files right now so again in the appetizers command n you know we're going to build them out later but let's at least get the you know the file created because we're going to need it so Swift UI view hit next we'll call this the appetizer list view right that's kind of the home screen if you will

uh again we're gonna do this three times command n new Swift UI view let's call this the account View create and then the other one is the order view right it's with UI View Order review so I just created three Swift UI views which is going to be our screens now for the text just so we know like

what's what uh here in the order view I'm going to actually put the text to say order view that way when we like actually tap our tabs we can see like okay yeah we are on on the proper screen so call order view order view account view account View and then appetizer list view appetizer

list view okay so back to our appetizer tab view here now I can start uh putting these screens in my tab View and then giving them their the proper icon the proper name all that good stuff for the tab bar so let's do that instead of text here I want an appetizer list view right we'll initialize

that with empty now here we want to put on a modifier right a tab item modifier and it has a label so let's get our Builder here and it's going to take an image and we want to do a system name because we're going to use an SF symbol that's pretty common for the tab bar and of course you

could use your own images if you like but it's pretty common to use the SF symbols so what do we want to use let's go to our SF symbols here we want a picture of the house right that's what is on the design so just type in house see different variations of it if you if you want circles cool

use that I'm just going to use the house outline here so command shift C to copy and we'll tab back to our xcode and for the string here paste in house I guess you could have just typed house that's pretty simple but yeah there we go and then now we need a text for the title so text

and it's going to be home that's what we want to call our tab so now let's hit resume on our preview here and see what we got here we Zoom we want to minimize that again there you go you can see we have our Home tab that's the only one and it does show the appetizer list view so let's uh

copy and paste this because we want this uh two more times right so copy again be careful copy paste errors they'll get you instead of the appetizer list view we want the account View and the tab item for the account view we don't want to be the home in the house you can see we have three tabs at the bottom they're all the home in the house that's not what we want uh so let's see

what we want for account again back to our trusty SF symbols type in person and then you can see all the the different types of you know person type icons you can have for your account again I just kept it simple and went with this outline person so again command shift C to copy tab back to xcode instead of house here in our account view let's command V for that be a person and then now you

see our tab bar updates there to a person and instead of it saying home let's call it account cool now you see our tab bar updating in real time down there and again instead of appetizer list view we want in order view in the image for the order pulling up the design again you can see it's like a nice little bag inspired by the uh Apple app

to actually shop you know someone might have shopped for an iPhone 12 recently don't know uh so let's just do our SF symbols again type in bag okay again various types of bags again I kept it simple just did bag I'm not even going to copy and paste that I'm just going to type in bag pretty simple there and again we don't want to be called home we want it to be called order

right so now you can see our tab bar taking shape we have home account order looking nice and now if we run this in our preview here click the play button again you get this bluish gray background now when we tap account view we can see it says account view tap order see it says order view uh we're good to go there now we'll stop this but you can see this is like the default blue color

again pulling up the designs we have this nice dark green as like our primary brand color so we want to make our tab bar you know have that color as the accent color but first we need to create that color so we did this before in the weather app but you go to assets hit the plus button

down here and we want to create a color set and here you go we're going to name the color brand primary I like to if possible Right sometimes the design doesn't call for it but if possible I like to have my colors be a generic name like like you know a brand primary right whatever app you're in Twitter you know YouTube like it's gonna have a primary brand color that way if that color ever

changes whether it's a completely different color or maybe a completely different shade like I don't have to go renaming everything like I know it's the primary brand color so tap on any appearance here uh and then pull out the right pane if it's not pulled out there we want to go to input method here we want uh 8-bit hexadecimal because I have the hex code I'm going

to paste this in here it's a hashtag zero zero six three three D for our dark green color hit return there you go and then we want this to be for any appearance like it's it's going to be the same dark or light mode if we wanted a different shade of it for dark mode we can change that but we're

going to keep it the same here so we're going to keep any appearance there so now we have a color called brand primary as you can see there so back in our appetizer tab View it's pretty simple right on our tab View we can do dot accent color and it just takes in a color so we do color and then uh brand primary and we're going to refactor our colors so we don't have to type like

I don't want to have to type out brand primary every time I use it we're going to refactor that later but now if I hit resume oftentimes in the preview you won't see this color type accent stuff so let's go ahead and run this on the simulator so we can see and then yep on the simulator you can

see the dark green home dark green account dark green order view so now our tab bar is set up let's spruce up our our views here real quick just so it's more obvious and we're going to need to do this anyway so stop the simulator we're gonna add the navigation view with the navigation title to each of these views right so if I go to appetizer list view let's wrap our text in a navigation View

put this command X command V put that in there and then on our text uh for now we're going to obviously change this but I want to get the visual there so we can see it better say dot navigation title and we're going to call this Appa tizers now I like to kind of put emojis in mine you

don't have to I'm going to do fries you can put any food you want in there um that that's kind of like an appetizer but I like my navigation view here um I don't know I just like how it looks right you got the Emoji then the name if you don't like that don't use the emoji if you want a different Emoji use a different Emoji cool but I'm going to copy this whole navigation view

that way it's quicker to type for the rest of our views here right so if I go to account view again uh over this whole text copy paste obviously this is not the appetizer list view just call this orders for now and then uh not appetizers for our title and you can see it updating in real time right on the right orders and then the Emoji I want is kind of like a receipt looking thing right

up see this is the danger I just realized I'm on the wrong screen so no this is the account right so this is for copy pasting and going too fast can kind of bite you so you always kind of want to want to check that we're on the account screen not the order screen got a little ahead of myself

and for account I just want to use uh a laughing emoji right you can use whatever you want we'll just put that there because the accounts are funny like aren't they right so again uh order View paste here now we'll do what I was talking about before uh we'll call this orders and then orders so hopefully this is repetition right we've built a couple navigation titles before so I'm going a

little quicker type in receipt uh and again I just like this look of my my navigation titles with the uh uh you know little Emoji so if we run this again oh we're not so we don't have a tab bar because we ran it from our order view right so our previews when we start them like it treats this is

like the entry point so let's make sure we go back to our appetizer tab view now we run it so now we have appetizers account with our our nav title bar and order so that's it for the setup and just the overall structure of our tab view uh just a quick review it's pretty pretty straightforward right you create a tab view in the view builder of your tab view you give it you know whatever

views you want and then you got to make sure you create a tab item modifier on that view so you get you know the image and the text and then again to change the accent color right whatever color the Highlight there you go dot accent color and then pass in whatever color you like in the next video we're going to dive into the new app lifecycle of Swift UI right you see appetizers.app like what is

this app thing what is this scene what is this window group what main like what is that we're going to talk about all that in the next video we left off last video getting the general navigation structure in our tab bar in place for our app in this video we're going to kind of take a little detour and talk about the app lifecycle that is new in iOS 14 and with swift UI now if you're

coming from UI kit you know you're probably used to the app delegate and the scene delegate that was introduced in iOS 13 but you know in the app delegate did finish launching with options that kind of stuff you had to run some code there well that's not here as you can see on the screen like we have a much simpler implementation now when UI Kit app delegate scene delegate that was the the

entry point for your app that's where your program started well how do we know how to do that in Swift UI well that's where this main keyword comes in right the main keyword acts as your entry point into your program now there's a function that has to be ran when you use the main keyword so it's a main function and you don't see that anywhere in here it was kind of Hidden Away by conforming to

app right you've been used to seeing us conform to view right our structs are conforming to view let's dig into app and see what that is so I'm going to command click on app to jump to definition well you can see it's a scene representing the content of the app right in scenes were introduced in iOS 13 real quickly a scene is what shows up and allows you to have

multiple windows right and part of a big part of Swift UI is being good on iPad Mac OS where there's multiple windows whereas if you're only on iOS you just have one window to worry about that's your app but that's why scene delegate was introduced in iOS 13 and this is kind of you know replacing the scene delegate right so like I said the body of an app conforms or returns

a scene right again we're used to the body of our view returning some view well now we need to return a scene which is again the window of our app and if I keep scrolling down you can see our body is a scene Builder right we we discussed view Builders how how the view Builder you know constructed a view is pretty limited it wasn't a typical you can't just write any Swift Code in

there very similar concept except now this returns a scene you know and it builds a scene but we're trying talked about that main keyword and how it required the main function well you see the extension on app here this is where this public static func main is right and let's actually copy and paste this URL and take a look here in the Swift guide and I hope you're getting a

little taste of like how I kind of like explore and develop don't get me wrong I I do a ton of tutorials YouTube videos articles definitely but when I want to dive deeper while I'm coding I just you know command click into something look at the definition read about it I'll make this bigger so we can see it here so again here's main right apply this attribute to a structure class or enum

a declaration do indicate that it contains the top level entry point for a program flow the type must provide a main type function that doesn't take any arguments and returns void so if we go back to xcode that's what's going on here the extension on the app protocol has the static function main so that's how our that's how our program gets started right we conform to app the app returns a scene

right again you're used to body some view well now we're doing body some scene the scene is just like the window of your app and it's different from like the old app delegate because you can have multiple instances of the same app uh you know whether on Mac OS or iPad OS right you can have that multi-window not really on the iPhone yet maybe that'll come someday but if you're doing

iPad or Mac you know you got to be familiar with scenes and then the final piece of the puzzle in this basic kind of implementation is the window group so again we'll command click now you can come in and click to jump to definition to see what we just did or if you want a more like nice kind of documentation option click and you get this little pop-up which is nice I typically like

to open a developer uh documentation because it's bigger so you can see a window group is a scene that presents a group of identically structured Windows okay that may be confusing but the overview let's read it here use a window group as a container for a view hierarchy presented by your app the hierarchy that you declare here as the group's content serves as the template for each

window that the app creates from that group right so back in our example anytime you open up a new appetizer app like again if you were opening this on the iPad and you opened up multiple instances of it or again Mac OS you opened up multiple windows every one of those windows is going to be initialized with our appetizer tab view right so what you're setting up in the window

group is what opens up when a window of your app opens hopefully that wasn't confusing but in our case we want to show the appetizer tab View and again that is kind of like how our whole app is structured that holds all our views uh Etc so again that's just the simple basic implementation again the main foundational knowledge that you should know of course this topic can expand right

if if you remember the whole did enter background we'll enter foreground did become active you know deep linking this can get pretty complex there's a lot that can go on here but again for foundational knowledge knowing how the app is structured how it builds a scene has a window group how you know main is your entry point again that's the foundational knowledge you should know if you want

to build on that I'll link to some resources below all right in the next video we're going to start building our data model for our appetizer object so we can start building out this appetizer list view that you see here and then eventually connect it all up with a network call so let's keep this thing moving we left off last video discussing the new app life cycle in iOS 14. in this video

we're going to start getting ready to build the list screen that you see here and that is going to be a network call we're going to get all this appetizer information uh via a server so we can populate that the first thing we need to do though is start building our model and building our appetizer object and looking at this screen you can start to see right it's going to have an

image or an image URL it's going to have a name a price if we pull up the detail screen you can see there's more information like a little description some nutrition information right so our appetizer object has a lot of properties on it and to know what properties we need to include on that we need to look at the Json that we're going to get back from the server so to do that you'll notice

a link in the description to this video there's going to be a link to our Json so click that link and open it up in Safari so I'm going to pull up Safari I'm going to command V because I already had it copy and pasted here's our Json real quick if yours doesn't look like that right if it looks

more I'm going to click this little monkey in the upper right if it looks more like this a jumbled mess you should probably install some Safari extensions or Chrome extension right if I go to Safari Safari extensions this will pull up the app store just type in Json viewer or something like that there's a bunch of them out there I got this Json peep that's the one I'm using there's other

paid ones you know that do more totally up to you what you want to get but I highly recommend doing that because you know as an iOS Developer you're going to be looking at a lot of Json it's nice if it is formatted nicely all right so back to Safari uh you can see right we have a request which is

an array and then here are our appetizer objects right we have a name Asian flank State description protein you know an ID calories price carbs and then the image URL so this is how we're going to structure our model based on looking at this Json and here's the downside about this one that I got from Safari like I can't manipulate the structure of this so I'm going to go to Chrome here and I'm

showing you both ways like intentionally if you're a safari user or Chrome user you can do this so again I'm going to paste the URL in there and the Chrome extension I use is called pretty Json again they're all free but the one in Chrome I like because I can see these little down arrows right like I can manipulate the structure so I can get a better visualization of it because oftentimes Json

can be like heavily nested and hard to figure out what's going on so here I can see we get a request that has an array of items that array of items is our array like I'm minimizing each one here right is our array of appetizer items so that gives you a sense of how the Json is structured we'll come back to that in a little bit right now I want to focus on our just the appetizer

itself but a quick note about showing you the Json like this there's a wide variety of how well documented an API can be you know sometimes the API is beautifully documented you don't have to dig into the Json the documentation will show you hey description is a string price is a double very well documented however that's not always the case it's very often that you know sometimes

the API is not well documented and you have to dig into the Json to figure out for yourself so that's why I wanted to show you this well that's one reason another reason as you can see by this uh URL up here is one thing I'm starting to do for my courses is build out my own back end so I can

start building my own uh apis and endpoints which gives me more flexibility to to be more creative in the types of sample apps I can make you're seeing the very very first version of it right now but my idea is that in future courses building out my own backend gives me a lot more flexibility in what I can build because to be honest with you my previous courses I had to find an API that was

like open and free didn't deal with like oauth or API keys because oftentimes that was outside the scope of the course so I was really Limited in like what types of apps I can build because I was limited to you know what API was free that also offered up you know the stuff that I needed in the format that I needed right so building my own backend hopefully I can do better stuff

I just wanted to talk about that real quick to give you the context on like why this is kind of a little hacky a little janky but I I didn't think it was bad to include in the course because oftentimes when dealing with Json and apis it may not be well documented so knowing how to do this is a good skill okay again using the structure let's build our appetizer object so in

xcode in appetizers do command n for new Swift file new Swift file not Swift UI view hit next and this is going to be called appetizer so for now we can keep a foundation I'll do struct appetizer and the first let's see these are going to be let's not vars because we're not changing these right we're just reading the data we're not like you know changing the name of something and

sending it back up to the server so these can be let's um so let's just kind of start logically here I'm going to go back to Chrome you know this order doesn't necessarily have to be the order you do it in again I like to be logical so I look at this I think ID should probably go at the top I'm thinking like ID name description price image URL and then like uh you know nutritional data

you can put them in whatever order you want but I like to put them in that kind of logical order so let's do let ID and that's going to be an INT but name that is going to be a string what did I say what was the next one uh yeah description price image URL let this description that's going to be

a string price it's going to be a double oops I could say let price and then let image URL there's going to be a string one thing to keep in mind here this is a very very common mistake you see how I made URL all caps here a lot of people will do URL and when using codable which we're

going to use you know more on that in a second it needs to match like exactly with what we have coming from the API right so if this image URL if this URL wasn't all caps but you made it all caps things are going to break so be very careful to name your properties exactly what's in the Json

if you're going to use codable which is what we are going to use to parse the Json now there is a thing called like coding keys that you can customize all that beyond the scope of this course we're not going to go down that rabbit hole just name your properties the same uh as you see here so you might even want to copy and paste that could be a safe way to do it we've

already we've already gone too far we haven't done that yet so image URL the URL is all caps um trust me that gets a lot of people okay so now we just need the nutritional information so let's calories and that is going to be a int let Pro you know what I'm just going to be safe let's do this let's practice what we preach here calories because again if you

misspell it it's going to be off okay so like calories equals in that's good uh protein copy paste int let what is this carbs and paste and it okay so now we have let's not make sure we didn't forget one right one two three four five six seven eight

one two three four five six seven eight okay cool just to double check make sure we have everything um we have the basis of our model object for the appetizer ready to go now I talked about codable how that's how we're going to parse our Json that was new in like Swift four so it's been out for a couple years now I'm not going to give a codable lesson if you don't know that

I'll link to some helpful uh resources hopefully you've been doing that by now um but I will keep it at a high level and describe what's going on it just won't be super in depth so you may be used to um you know conforming to codable like this right just codable well if we click into codable little lesson here all codable is is it type Alias for conforming to both decodable and encodable first

of all we just need to uh use decodable right there's no need to for us to encode data so real quick what this does is decodable when we get Json from the server it will decode that into how our appetizer object right so when we just retrieve data and receiving we just need to decode it we don't need to encode it when you would need to encode your data is like say we were downloading

the appetizers we were manipulating them like I said maybe we were changing the name changing the price and then sending them back up to the server so before you send it back up to the server that's when you need encodable right we're not doing any of that so there's no reason to conform to encodable just unnecessary so we're only going to conform to decodable because again we're just

decoding the data from the server and like I said in order for decodable to work your your structure has to be exactly what's expected from the server and if we go back to our our Json here remember the structure right and just at a high level we have request and then an array right the Json is just a dictionary key value pairs so uh we have it's like there's one layer of nesting going

on here so we can't just decode our response from the server into an appetizer we have to decode it into that request that has an array of appetizers so below this let's create a response object to handle that that way codable or decodable Works smoothly so I'm going to create another struct right below here it's kind of like a helper struct if you will um we'll call it APA Tizer response

and oftentimes you have to do this if your your json's like really really nested here but just like what we do we have let request and then that is an array of appetizer right that is what we built here is this right so this is this object right here is our appetizer response it has a property of a request and that request is an array of appetizers so we're just

mirroring the structure of the Json so that's why we have this appetizer response with the variable array of appetizers okay so now that we have that response and that is getting ready to accept our Network call and we have our appetizer the last thing I want to do is create just a little bit of mock data for when we build our list view in the next video it's nice to have like a mock appetizer

to work with since we're not going to have our Network call implemented yet so we can structure our UI using the mock data so we're going to build that and we've done this before in an app but I usually have this you know usually once the app is done being developed this I delete this stuff it goes away but usually during development it's nice to have this uh mock data type stuff here

so mock data first thing we're going to have is a static let sample appetizer and that's going to equal an appetizer we're going to initialize a new one here again it's initialized based off of you know the properties we just had here so ID and I'm just going to make stuff up here because this doesn't matter right this is just to populate

our UI to make sure things are looking good so the name we can say test appetizer description this is the description for my Appa Tizer it's yummy and again we'll start uh lining

up our parameters like this we're going to do this right now because it's annoying okay so the price we can say this is 9.99 image URL I'm just going to leave blank right now because we're not downloading images yet that's fine we're going to use like a placeholder image as well calories cool 99 protein 99 you can put whatever numbers in here you want again this is

just to get the structure of our UI looking good so oftentimes in your sample data it's nice to test um you know extremes right like if you wanted to test a really long Advertiser name you can test this here so that's our sample appetizer that we're going to use and then in the next video we're going to need an array of appetizers to populate our list right remember if you

have a list you need an array of something to populate it so we're going to do static uh let appetizers equal and then I'm just going to do sample again this is just dummy data just like give me four sample appetizers and the last thing we're going to set up in our mock data is we need a test image so if you open up your XC assets right now we just have our our colors

here but we're going to add an image to that and I've attached the image to the uh to the video in the description you'll you'll see an image down there the Asian flank steak image so I'm going to grab the Asian flank steak jpeg drop it into my images and we're good to go remember we're going to be downloading the images from the server this is just a test one to structure our UI so back to

our appetizer object uh like I said we created our object based on the Json that we are getting back from the server uh we created our response object to handle the structure of the Json and this is necessary when we're using codable if you're manually parsing the Json you don't have to do this you can you can dig through the Json manually but we are using codable so we're going

to do that and then we set up our mock dado the sample Advertiser and just a basic little array just to you know help us build the list in the next video we left off last video getting our appetizer object ready in this video we're going to build this list view that you see here so back into our code we already have our appetizer list view created remember kind of our dummy mock-up

for the tab bar but all we have in here is a text that says that well we're going to replace this with a list so let's get rid of all this we'll retype that navigation title later list and then open it up so you got a lot of uh possible you know initializers here we just want the simple

one uh blank which is our array ID and row content so here you can see the data we have is a random access collection which is an array so the array we're going to use is our mock data dot appetizers right that's that array we created in the key path here we wanted to do dot ID and if you remember we

can conform to identifiable to not have to do that we'll come back to that in a second but right now we want to just use the ID I want to dispel that out for you and then the content here I can delete that because we can just put the viewbuilder here then we need to do appetizer in right so this in

our list here we're going to have uh it's going to iterate through the mock data.appetizers and

we're going to get an appetizer for each one and then in here we're going to create our cell for each appetizer but for now just to get xcode to stop uh yelling at us I think I'm missing a closing curly brace here yep for now to get X go to stop yelling at us let's just do text and then we'll use appetizer dot name right we'll just print out that just the name of

the appetizer in our list view uh just to get this structure you know running so let's open up our canvas so we can see that here get this going I forgot to start that hit resume we are on the iPhone 12 Pro it is 75 cool there we are test appetizer remember if we go back to our appetizer that's what we named our sample so that is working back to our appetizer list view let's

add that navigation title uh to our list remember not the navigation view the navigation titles goes on the element inside the navigation view so dot navigation title and then you know command control space to pull up the Emojis we wanted french fries you can put whatever you want in there appetizers there we go let's get our our navigation title back okay so again that is just

basically how you create a a simple list right list initialize it with with an array of an object um we're going to go ahead and conform to identifiable right now so we don't need to have this ID but I'm going to run through the rest of this real quick so as it's iterating through the array of appetizers we get you know just like in a for Loop we get an appetizer variable that

we can use here so for every appetizer we're going to create a text cell that just has the appetizer.name that's what's going on here so that's the very very Bare Bones minimum of a

appetizer.name that's what's going on here so that's the very very Bare Bones minimum of a list but again first back in appetizer uh let's make also make this conform to identifiable and then now in our list view we can get rid of this ID just to clean stuff up a little bit now one thing our sample data I mean it's going to work to show stuff but if we were doing this

more advanced it wouldn't work and and I want to point out why that it uses that ID as a unique identifier a way to identify each object well if you look at our appetizers right you know we we have our sample appetizer with an ID of zero zero one whatever well we have four of the same sample appetizers in there right so they're all gonna have the same ID it's going to be fine for

the basics of what we're using but I want to point this out that you know if we were moving items uh within the table or deleting stuff and inserting stuff um you know that would be an issue it's not going to be an issue for us but I wanted to point that out okay so appetizer list view here we go let's start creating our cell because just this text not exactly what we're looking for we want

to build this cell that you see on the screen and it's going to be a challenge for you you can pause right now pause the video if you want to try to build out this cell here basically just replace this text with uh spoiler alert it's going to be an H stack um if you want to build your H stack

here give it a shot go for it but now is your last chance to pause if you want to try to build that yourself because uh here we go okay so looking at the structure of the cell like I said it's it's an H stack on the left side of the hdac we have our image but then on the right side of the hdac

we have a v stack that holds our title and price right pretty pretty simple structure we've done something similar before but let's walk through this right so overall let's get rid of our text let's make it an H stack the review Builder here the first part of our H stack is going to be our image like I said we're going to initialize this image with a name right because remember in our

XC assets we brought over the Asian flank stake so again to prevent typos command C appetizer list view is just paste that name in here the Asian flying State Bam um not exactly what we're looking for and that's because the images come in kind of raw right so if you remember on all the images we want to do resizable again I'm not going to say you always

want to do that but uh 99.9 of the time you're probably going to want to have resizable on your images so that resized it to fit the screen however the aspect ratio is off right that's not what it's not what our image looks like so we need to add the aspect ratio right so aspect ratio content mode we want to fit to the entire area but we don't know the area yet so that's going

to look like no difference we need to give it a frame right so give it a frame with the width and height you see that default to do 100 by 100 but you'll notice our image is more of a landscape it's actually 600 by 450 so it's not a perfect square but our frame is a perfect square so you

can see because we did fit it's not filling the entire Square let me go back to fill and you'll see now it will fill the entire square but that's not the look we want we want want to do fit and we want to match the aspect ratio of our images this is where you know knowing your design and building

to a design spec comes into play so we know our images are six 600 by 450. so we want to keep that aspect ratio just at a smaller size so we're going to do 120 by 90. okay that gives us the the size we're looking for you know based on our design and we don't need this alignment parameter okay so

the last thing we need to do for our image is our Corner radius uh of eight remember it's got that subtle subtle Corner radius not overbearing but it just you know doesn't have so many sharp edges I like that look so that's our image in our H stack uh remember what's on the right side of our hdac is the v-stack which contains the two texts holding our price and stuff so let's do v stack

scroll up a bit and it's going to be a text as you saw here and the text we want to put in here is going to be the appetizer name so appetizer dot name and remember this is the uh the appetizer that we're iterating through array and creating each cell right so again we have all the same sample data in there so it's all going to say test appetizer but like I said this is

just to get the structure of the UI and then we want this to be a font dot uh title two is what we're going to go for and then we want this to be dot font weight of medium and again this is just me matching a design spec right if you want to change the look and feel of this make it super

big and bold or tiny and small have at it play around with this this is just the design that I came up with so that is the name however below it you know smaller less emphasized we want to have the price so here we can do text and here we can't just do appetizer dot price because that's a double right text needs a string so we need to use some string interpolation here appetizer dot price

but we're going to want a dollar sign in front of it now you'll notice uh we don't want all those decimal places right nine nine nine point zeros or like we don't we don't want that so within my string interpolation if I do comma specifier I can add a string and it's this is a little weird I get it percent dot two F that's two decimal places if I wanted no decimal places I would just get

rid of that too and you can see it's going to round up to ten dollars instead of 9.99 one f one decimal place there you go you can see on the right we got one decimal place we want two decimal places because this is a uh you know a price and then now as you see in the design this is a it's

like a lighter gray it's not it's not the black text color so we want to do uh foreground color dot secondary right so this is kind of like that secondary color you can see here that'll gray it out and then we want to do dot font uh weight dot semi bold right we do want the price to be you

know kind of bold now you'll notice here in our text it's centering the items here right see test appetizer in 999 are centered well we want them to align on the left so in order to do that we can update our v stack here to have the alignment parameter I don't know if we I don't think we've used this yet we've used spacing but we haven't used alignment right so there you go you can do

alignment spacing then content we're just going to do the alignment and we're gonna do dot leading right so now if you look here now they all got pushed to the left uh to be leading and I feel like the test appetizer and the numbers are too cramped so we are going to use the spacing parameter uh as well we're going to give that a five to start here right you see that just spaces

out a little bit I'll do that again Watch the test appetizer and the price you see super cramped and if we go back to five just a little bit of extra spacing so you can tweak your design a bit and then another thing I want to tweak about my v-stack here again we're working with this v-stack just the stack of the name and the price I feel like it's too cramped up close to the pictures

so I want to add a little extra padding just to space that out a bit so here at the bottom of my v-stack I can do padding I can do padding all around that's fine you're not going to notice the difference here if I wanted to be very specific though remember I can do padding dot leading and there you go that only gives the padding on the Leading Edge now you can't see it because nothing

is on the right but now there'll be no padding on the top no padding off to the over to the right just padding on the Leading Edge okay so we have the basic structure of our cell here let's run it into simulator just to see we're getting make sure nothing is weird is going on before because we're

going to refactor this next but I want to again run it to test it because I always like to make sure my stuff is working before I refactor right if you refactor something it's not working yet uh that's tricky but anyway here we are in the simulator scrolling up and down uh things seem to be fine I can't tap it we haven't added that yet but again our cells looking good all right so

let's refactor it and wrap up this video so this is common what you want to do for your cells here in our cell if you remember is basically this H stack that's the cell that we just built so we want to take this H stack and move it into its own file called you know appetizer list cell now I just said move it into its own file that's fine remember organization is subjective I wouldn't

argue with you if you wanted to keep it in this file but just move it like down here to the bottom wouldn't argue with that at all I don't know I like having a folder of cells because oftentimes cells get reused so uh just a habit of mine I like to create a folder called cells and put it there we're going to do project reorganization in a few more videos so you know don't worry

about creating that folder just yet but let's create that file so in appetizers command n it's going to be a swift UI view hit next and so if your view is going to be appetizer list sell hit create and then we can literally just go to Advertiser list View copy the hdac and then go to advertiserless cell get rid of the hello world text it in there but

you're going to notice something right we don't have the access to appetizer so we have to have appetizer be a variable on our list cell so we can pass the appetizer into the cell and then it will create itself so we'll do let appetizer that is of type appetizer I return here do command B and now the only thing missing is our preview remember I said you got to initialize your previews with all

the information you need the information our cell needs is an appetizer right so fix that appetizer and then this is why we created our mock data so mock data dot sample appetizer right if we didn't have that mock data we would have to do this right we'd have to do appetizer and then initialize that and then we'll get this long initializer it gets ridiculous this is why we create mock data.sample

appetizer nice and clean we got it right there now if I hit resume on my preview we should be able to preview this cell and there it is now what looks different than what we saw on our cell like look at all this padding here is because right now it's just an H stack by itself right in in this preview

it's not in the context of a list right a list has very specific formatting that if we go back to our list view like it handles all the formatting of a list so that's why the previews look a little different but back here in our appetizer list view we can get rid of this H stack right be gone and

then now we can just replace that with appetizer list sell and then you'll see that takes in an appetizer and then we're just going to pass in the appetizer then we we have here as we iterate through our array so right that cleans up uh this screen nicely right you just got a navigation view with the list in it you can see the list has appetizer list cell with an appetizer and

then our navigation title of course this is just the very basics of our screen but you can see how it reads nicely pretty easy to understand what's going on here now this is just our mock data right the real app we want we're going to hit a server we're going to get the appetizer Json we're going to parse that Json with quotable then we're going to populate our list with that downloaded data so

let's start that process that's going to take us a couple videos to do but the first step in that process is to set up our Network call and make sure we're getting the right data back from the server so let's do that we left off last video getting the structure of our appetizer list view cell up and running now we need to start building Network call to populate this with actual

real data from the server not our mock data so the first thing we're going to do is set up our network manager real quick disclaimer there are a bunch of different ways to do Network hauls for example if you use Alamo fire that's fine if you make your network calls much more generic cool if you use something like a request Builder awesome there's so many different ways to do this

I'm keeping this very basic very fundamental right down the middle you know for learning purposes so just keep that in mind if you have a different way of doing Network calls feel free to do that that's fine if you're here and you're not familiar with network calls this is a good opportunity to kind of learn the fundamental way to do it and then you can explore other options later okay disclaimer

out of the way let's create a new file in appetizers command n Swift file some to create a network manager hit create and it's going to be a Singleton so we'll do a final class called Network manager and the first thing we're going to do is static let shared right this creates our Singleton

network manager and then I need a private init and just an empty implementation of it so what this did was create our Singleton right we have a we'll do Network manager.shared to access the Singleton and then we're gonna have functions on this that you'll see here but that's the basic setup of the Singleton why a Singleton you may ask well if you look at Apple's documentations on that

they actually recommend things like Network managers be Singleton there's a whole other pattern other than doing things like manager again that's fine keeping it simple and sorry if I keep repeating myself with these disclaimers that's just four years of hearing thousand thousands of comments about my code like I always I can just see the comments before they happen so I try to

give those disclaimers if you're sick of hearing that I apologize so the properties I want to set up on our network manager first are the URLs so we'll do static let base URL and I'll explain why I'm doing this here in a second equals and this is going to be our URL string that we use to see their Json again that is going to be in the description of the video feel free to copy

and paste that here so it's a string command V and that's not our base URL that's really like the whole URL right so the base URL would be you you know the Heroku app.swift UI fundamentals and then right each individual endpoint would be slash appetizers slash whatever other endpoints we have this is going to be the only endpoint on the app but I'm showing you how I structure it for like a

kind of like a real app so for example I would do static under my this is kind of like a whole list of URLs that I would have static let appetizer URL uh equals and then the string would be base URL plus and then I would take the appetizers and put it uh here and then make sure we uh Delete the

appetizers here I usually keep the slash there so I don't have to repeat it in the in the back end of my URL every time so that's the general setup of our network manager now what we need to do is write the individual functions that will be our our Network calls right this app is going to have two we're going to have one to get the appetizers retrieve that from the Json that we just saw and

then we're gonna have one to download the images from a URL you know to download our appetizer images so those are the two Network calls that are going to eventually be in our network manager for right now we're just doing the git appetizers one Funk get appetizers and then here's our completion Handler completed and it's going to be an escaping and that is going to return a result

and then the result is going to have two values one is going to be our array of appetizers I'm going to explain this give an overview of this real quick when I'm done typing and then the other piece of information the result is going to have is an error we're going to create our own custom error here in a bit but for now to get xcode to stop yelling just call it an error and

that's going to return uh void all right and then open and close brackets to get the scope of the function so that is our function signature so I'll run through this now I'll keep it at a high level because again results can be a whole video in fact I've done a whole video on results I'll link to that in the description if you want to dive in I've done a whole video on Escape enclosures so

I'm not going down those rabbit holes but high level the function is get appetizers once that is completed we're going to have a result that result is either going to have an appetizer or I'm sorry an array of appetizers which is what we want that's the success case or it's going to return an error that would be the failure case and speaking of that error let's take a second real quick to

build our custom error before we start writing this function because we're going to use that custom error throughout this function so I'm going to go to appetizers here command n for a new file new Swift file we'll call this AP for appetizers air I really like to preface it with the first two letters you know of the app so AP air and we're going to make this in enum called AP uh air

and we're gonna have four cases right case uh invalid URL case our URL is messed up case invalid response case invalid data so invalid response is you know when we get like a 404 or 500 or whatever from the server invalid data is if you know the data we get back we can't parse that

out it's something's wrong there and then case uh unable to uh complete we're going to use this one for uh just the general error right like if the Wi-Fi is turned off or something like that you'll see how we'll use these in a second but I had to create them before we can use them so back to our network manager okay so now instead of returning just a swift error oh I forgot something forgot

something back to AP error in order to use uh the AP air here it has to conform to Swift's error protocol so that's what I forgot AP error can't just conform to nothing it's got to conform to error there we go forgot key piece of information here so now in network manager I can replace this

generic Swift error with our AP error and that will work because we conform to the error protocol cool and like I said you're going to see how we use these errors in the network call so I'm going to run through building this function I'll talk through it but at the end I'm going to come back and walk through it just like I always do to hopefully make it make sense so the first thing I

want to check on is make sure the URL that I'm trying to use works so guard let URL equals and we want it to be because we don't want to create a URL object right not just the URL string we have to create the URL object and we want to create that URL object from a string right there you go and the string we want is our appetizer URL right because we're doing git appetizers that's

the endpoint that we want to hit appetizer URL and then our guard statement needs an else right so what we're doing here basically is when you create a URL from a string it's an optional in case it doesn't work so if we actually get okay what is okay duh I made this static instead of private oops got my my keywords mixed up there okay so now back to what I was saying URL uh from

a string returns an optional so we want to make sure you know it's not nil if it's nil that means we couldn't create a URL object from the string so we want to return an error right so we want to call completed this is our completion Handler here and in this case we want to initialize that with

a DOT failure case and then the error we want to pass in right this is how our result works is we want to pass in dot invalid URL this way we know what type of error happened here and then we'll hit return so cool get used to this structure we're going to be using something similar a lot to

check for all the other data but right now we're just checking to make sure we have a good URL before we try to use that URL to make a network all that's basically what's going on here and again if we have a bad one return that specific error so that's the first check the URL now we can actually start creating our data task to download the information so we can do let task equals URL

session dot shared dot data task and we want to do with request but we want to have the completion Handler right you see we want to get back data response or an error right so data task with request that has that completion Handler so the URL request we want to create let's create a new one URL request with the initializer you can see it takes in a URL good thing we checked to

make sure we had a good URL up here so we're going to pass that URL in now the completion Handler I'm just going to hit return here and I can name these whatever I want but I'm going to name it basically exactly what they have data response and you can see they're all optional so this is what we're gonna have to check to make sure we have these these items right and I don't

like these parentheses here they're optional less clutter keep them if you want okay so now uh what we're going to get back in this in this completion Handler is data response and error and they're all optional so that's what you're going to see us do we're going to unwrap all these optionals and handle them accordingly so first let's tackle the error case so guard let

underscore we're not going to be using the error equals error else and we're going to pass in the uh the error here unable to complete so else we'll do completed with the failure case of dot unable to complete because again this is this usually happens when you know the Wi-Fi is not working that's just one example then we want to return here so basically we're saying hey if error is

not equal to nil go ahead fire off the failure case and pass in unable to complete as the error okay so that takes care of the error same thing with response so guard let response equal response oh okay response has a p in it I thought that looked weird when I typed it but you know my mind's elsewhere trying to explain things um cigar that response equals response and then we're going

to cast this uh as an HTTP response because we want to get a specific code here so if we have a good response let's also make sure the response dot status code equals 200 and then now we'll do else and let me walk you through that here so basically what we're saying is hey do is response not nil cool if it is cast it as URL response and then take that response that we got and then

check the status code on it to make sure it's the 200. if you're not familiar with HTTP status codes 200 is usually the hey things went good so we're making sure we got a 200 back this is where you could check against the status code like hey if I got a 404 send back this error if I got a 500

send back this error right you can really tailor your error messages based on the status code we're not going to go that deep we're basically just going to get a pass fail just to keep it simple so if we don't get a 200 here or if responses nil for some reason we're going to call complete did and then pass in the failure case of dot invalid response again I'm keeping these kind

of high level engineering but we've taken care of our air we've taken care of a response data is the good stuff right data is our array of appetizers that we get back if we get it but we got to check to make sure we have it first before we use that data so again uh guard let data equals data

else completed dot failure case with DOT invalid data and return and I forgot the return up here right because if we if we get a bad response we don't want to run the rest of the code if we get bad data we don't want to run the rest of the code right we just want to exit out that's why we're returning right there okay now that we made sure we have data now's the the good

stuff all this up here was just all bad stuff right checking for all the errors if we made it past all those checks now we have our data and now we can parse that data and create our appetizer array from the Json so we'll do that with a do try catch block so do we'll say let decoder equals a Json decoder remember we talked about encoding and decoding we want to

decode the Json right so let's create our decoder here and say let decoded response right this is where this will give us the uh our object here equals and here's where we need to do the try right so decoder dot decode and then it's from uh well what type do we want to decode and this goes back to our model right review from from last video here back to our appetizer right if we

were we can't just decode an array of appetizers because remember our Json is not structured that way our Json if we look into our response remember our Json was structured with a request that had an array of appetizers so in in decodable this is what we want to decode our appetizer response speaking of I forgot to do this let's go we got to make this decodable and a note on codable and

decodable the reason I can just add that and not have any extra code is because all the underlying types conform to codable and the underlying type here is an appetizer but if you look at our appetizer all these basic you know things right int string double int those are all going to conform to codable if you have really weird unique types you may have to write some X extra

boilerplate code but as long as you're using these fundamental ones or foundational ones I guess because it's in Foundation you know you'll be fine to just conform to decodable without writing any extra code so anyway we're going to decode our appetizer response which is going to have an array of appetizers attached to it right so by decoding the response we're also decoding all the

appetizers as well okay so back to the network manager that's what we want to decode the type we want is our appetizer response you have to dot self here and then what do you want to decode that from right it takes in data well this is the data that we made sure we had up here right so passing that data cool so basically what we're saying here is from the data that we have decode that data

into an appetizer response and again our appetizer response is going to hold our array of appetizers and speaking of that array of appetizers as a reminder look that's what our result types returns an array of appetizers so now we want to handle the success case right this whole time we've been doing completed failure talking about failures right now we want to do completed uh

got success and you can see the success case takes in an array of appetizers what I just pointed out up top so now we want to pass in decoded response dot appetizers and do a command B I think it's telling me that yeah I need to do the catch case here I think um let's put this in here and let's just do completed uh so basically if we can't decode correctly we're

going to pass in the dot failure case uh and that case is going to be uh dot invalid data right so our data was messed up oh I'm sorry that it's not decoded response.appetizers it's decoderresponse dot uh request because if you look at our model and we just named it that way like we could have named this appetizers but I wanted it to match the structure of the Json so that's why we did that if

you want to name it differently fine but that's why we do decoderresponse dot request because that's what it is and then again if that decoding fails we completed with the failure of invalid data and then the last piece of the network call puzzle that many many many forget and it always trips people up and this is why I like this error right here it says hey you initialize a task but

you never actually use the task that's my reminder to do task dot resume down here and I think I'm in the wrong scope too many curly braces so I didn't get the auto complete because I'm in the wrong scope so now we do it down here there we go command B make sure that's all good cool all right

as a review I'm going to do a quick high level run through of what we just did so we created our network manager right our share we're going to be using networkmanager.share.getappetizers

right and you know if you had more Network calls you'd be using that as well same thing with here with our URLs um this is all we're going to have but you know that's the structure if you had more URLs here we have our function get appetizer it has a completion Handler that's escaping that returns a result a result has a success case and a failure case in a success case we

get back an array of appetizers in a failure case we get back an AP error which we can handle later so we check to make sure we have a good URL if we don't have a good URL return failure within invalid URL here we create our Network call with the URL request based on that good URL we got our

Network call is going to either give us back data response or an error so we got to check for all that stuff because they're optional so if I have an error cool return the AP error called unable to complete if my response is is either nil like I don't get a response or it's the wrong status code like a 404 you know return the failure invalid response be done same thing if for some reason

I don't have data okay return the failure get out now if we made it past all those checks we have good data so now we're going to try to decode that data using our Json decoder this is where the codable you know decodable protocol comes in we decode that into an appetizer response which we created in our model uh that Advertiser response has a property called request which is our array

of appetizers so if this all goes well that means our data is good we've you know decoded our array we have it here so let's call completed.success and again remember success case gets the appetizer and so we're going to pass back our array of appetizers in the success and then if this decoding goes wrong we pass back invalid data when your decoding goes wrong it's you know remember I

talked about in your appetizer model how maybe if you had a misspelling here or if you use image with lowercase URL like that's when it'll trigger uh this decoding error here down here so if you're if you're having trouble in other apps or network calls or even in this one and this keeps firing off double check to make sure your model is properly formatted to what you're

expecting back from the Json and then you call task.resume to actually fire off the network call so I know that was a lot if you're if you're familiar with network calls that was all review old hats if you're new to network calls you know that may have been a lot happy to answer any questions in slack or in the comments but our network manager is set up we're ready to use this

now we just got to connect it to our list screen and we're going to handle that in the next video last video we got our network manager in place as you can see here so now we just need to connect this all together right we got all the pieces in place let's connect it so back to our appetizer list view here currently we're using our mock data.appetizers well we're going to need an

array of appetizers to populate from our Network call right so let's create a state variable here and really how this video is going to go spoiler alert I'm going to get everything working in the view and then we're going to refactor into mvvm okay little heads up I like doing it this way because again I want to get it working in the view and then refactor rather than refactoring

and wondering like one is my network all messed up or is my refactor messed up that's the that's the trouble when you refactor too early you never know like which is the error and it makes you know debugging it hard but if you get it working in the view first and then you refactor you know like your refactor broke it not that right so that's why I do it this way so anyway State

private VAR called Appa tizers that is an array of APPA Tizer and for now we'll just initialize an empty one so how this is going to happen is we have an empty array to start we're going to make our Network call our Network call is going to populate that array and when we populate this array because it's a state variable that means our view is kind of watching it and our array

will have changed so that change is going to trigger a redraw of the view but now when it redraws the view we actually have appetizers in our array and that will populate so that's the flow we'll go over that once we get it all working as well so one thing we haven't done yet I don't think is we haven't added functions to our view that is possible and I know when

I was first learning Swift UI like it's it's once you see it it's like oh yeah of course you could have functions it's just destruct but I remember the first time I saw it I was like oh duh that makes sense you can have functions so anyway let's do uh Funk we'll say git Appa tizers and here's where we're going to use our Network call so we'll do Network

manager.shared.getappetizers you can see the completion Handler we get I'm going to

manager.shared.getappetizers you can see the completion Handler we get I'm going to hit return I'm just going to call this result uh you can get rid of the parentheses again so here remember our result is a success case or a failure case success we have our array of appetizers failure we have an error we're going to handle errors in a future video

um but we'll come back to that so we do a switch off of our result right because as the cases and the first case is uh dot success and you see we get an array of appetizers here so we'll say let APPA tizers right that's the we basically give a variable name to what we get back here yep switch case must be exhaustive cool let's go ahead and fix that so I don't have to type cool

failure case and we're going to say uh let error we're not going to use that error like right now if I forgot the the colon after that um we'll just do print error dot localize description um we're just gonna do that now we're going to actually handle that later but we're worried about the success case right we want to know what to do when we get our appetizers so when we get

appetizers passed back we want to set that equal to our array up here remember I said our Network call is going to populate this array so cool in our success case we have an array of appetizers so let's set uh self dot appetizers equals appetizers and we want to make sure it's the local variable here that's what this l means by the way if you're not familiar with these little icons it all means

local so there you go and you see it's also green to let me know it's this one and then white to let me notice this one and that's because they're named the same thing and that's also why I had to use uh self here well I could capture self up here new and Swift 5.3 so I didn't have to use

it but but I would have had to use it anyway to differentiate between the appetizers on my view and then the local appetizers so one other thing that will will get you is think about it we're on a background thread right now with our networking uh all your UI updates should be on the main thread well what happens here and this kind of threw me for a loop when I was first learning

is uh you know usually in UI kit you could set the data on a background thread that's fine but Swift UI is different because setting the data is triggering a UI update so this needs to happen on the main thread so you want to get on the main thread so dispatch Q dot main Dot async and then

the code here and then we're going to cut and paste our code into there so we're on the main thread now okay so we have our function right we're going to use git appetizers to make our Network call if it's a success set the appetizers if it's a failure handle the errors we're going to do that in another video but uh when do we call this right because remember in the

view Builders like I can't just call a function right remember we talked about how viewbuilders were limited well there's a modifier called on up here which again is similar to you know view will appear and there's also on disappear which is like view will disappear so here in our navigation view we want to do on up here and we just want to the closure here but right we just want to call git

appetizers right so when our navigation view appears we're going to make this network call git appetizers the network call is going to fire off it's going to set our state variable equal to the appetizers we get back which is going to trigger a view redraw which now we don't want to use Mock data.appetizers I'm glad I did that run through because I forgot this we

can just delete this and do appetizers right we want this variable so Moment of Truth we've done all this setup over the past two videos uh let's see if it's working so I'm going to run it on the simulator this is legitimately the first time I'm running it so fingers crossed okay so let's debug this I messed up somewhere we'll do this it's kind of live

um I thought this would work I messed something up somewhere right so it printed off the air.localized description right that's what you see here operation can be completed uh AP

air.localized description right that's what you see here operation can be completed uh AP error three so if I go to my AP error I I can print off a better thing looks like unable to complete because I think these are I don't know if they're zero indexed here tell you what again live debugging this will be educational right so inner network manager I'm just going to add

uh some break points real quick just to see which one uh it hits I believe it's I believe it hit the unable to complete but um let's see here run it again see what breakpoint we hit okay so we're in here unable to complete so we're getting the big error so that tells me maybe something is messed up with my URL up here okay so let's test something I went back and when I copied

the the whole URL here maybe I messed something up here pasted it there uh so we're going to use here instead of appetizer URL we're going to use base URL and it's a static variable so I gotta do uh network manager dot base URL but that is going to be this whole URL that I literally just copied and

pasted that was working in our Json preview like on Safari so this will tell me if it is in fact my URL or not again we just process of elimination on debugging here again I'm debugging on the Fly not this is not part of the script man still in completed unable to complete so something else

is messed up here okay I see it now I see it now so I'm going to actually command Z to undo what I did to get this back to appetizer URL and get my base URL back to just with UI fundamental slash and then appetizers and it's the it's right here simple mismanagement of unwrapping the optional and let me walk you through this so you can see in case you run into something similar this was

just a a brain fart slip up thing right so when I unwrap this error listen Maybe maybe you picked this up when I was typing it if you did Kudos on you but think about what I'm saying here right I'm saying if I have a value for error great continue on if air is nil then I go into my

uh statement well error being nil is a good thing right you know response being nil is a Bad Thing data being nil is a bad thing but error being nil is what you want so instead of guard let um I do if let get rid of the else so now if you read if let and how that reads you're saying okay

if uh error has a value then go into the scope right so if air has a value now I want to do this completion Handler uh if error is nil then we're going to skip this whole scope entirely and move on and that's the behavior we want so let's undo these breakpoints that might be a little overconfident I'm like 99.9 sure that's what it is but you know famous last words so let's run

this again uh things should be working fine again a little bit of a live debugging there don't okay great it's work now our pictures are the same because remember we're not downloading images yet but you see we have Asian flank steak black and shrimp buffalo chicken bites you know we have the correct counts we have all the names and the prices um you know we're gonna download images in

a future video so anyway apologies for that little detour down the live debugging that wasn't you know on the script but you can see how simple little errors uh you know can trip you up and here's my excuse right call an excuse if you want but you know when you're filming yourself you're you know recording you're you're kind of only half engaged with the actual code part because you're

worried about explaining it correctly and talking and looking in the camera all this stuff um so for me whenever I'm recording my videos little slip UPS like that happen a lot because again there's a lot of other stuff going on that's that's my excuse and I'm sticking to it but hopefully that was helpful you got to see me debug a little bit and you saw this is what it is most of the

time a silly little error but but anyway skip the simulator back up uh we're working we have this connected we're good to go I'm going to stop this and go back to our appetizer list view hit resume there so we have our Network call running working however it is in our view right you don't want you don't want your network calls in your view right this is what you want in your view model right you

want your view to be as dumb as possible so here's the challenge for you we're going to do this here in a second but the challenge is you know we've done view models a couple times now in previous apps so see if you can refactor the network call into the view model right create the view model set it up move the network call to the viewmodel and make sure things are all connected and get it

working again that's your challenge you have three seconds to pause and try it three two one all right now we're gonna do it okay so to create the view model in the appetizers folder command n for a new file new Swift file hit next we're going to call this the appetizer list view model hit create cool uh we want to import Swift UI because we're going to be using observable object and then this

is a final class Appa Tizer list view model there you go and again we want to conform to observable objects not observed object observable object now let's create this in our appetizer list view we'll do at State object remember if you're initializing your view model you want to use State

object if you're passing the view model in from another previous View because you needed data from that view use observed object I'm just again reviewing pounding that into your head now we do view model and that's going to equal a appetizer list view model and initialize that there we go so

that's our view model I'm going to cut this state variable so command X go to our appetizer list view model command V to paste that in now it's not State it's published remember your your view model and observable objects needs to broadcast when it changes and what we're setting up on our Advertiser list view is we're setting up to listen to those broadcasts that is changing so in order

to draw broadcast the change use the property wrapper published okay so now our appetizers are in the view model now we're getting all kinds of Errors because we don't have the appetizers here so let's well first of all it's kind of fix some spacing we look ridiculous and then now instead of just appetizers we are doing view model dot appetizers good to go here and then here in our

Network call uh get this whole thing out of here so command X create this function now again our view is as dumb as possible appetizer list view model paste the function here so now now we have viewmodel dot get appetizers you can add some spacing let it breathe a bit the code doesn't change right because our network manager is still getting appetizers and then we're still setting

these appetizers and again because this is an observable object and this is published whenever this array of appetizers changes it's going to broadcast its change and back to our list view because we have a state object called viewmodel now we're listening for those changes so the same process is still going on just like a little in a slightly different way and the last piece of the

puzzle here is get appetizers like we no longer have that function here who has the function right the view model so now we do view model dot get appetizers do a command B make sure we're good to go hit resume on the preview even though there's nothing to show because we're relying on the uh the network call to show our appetizers so now uh let's run this and then I'll I'll walk

through it one more time again to just like really drive the point home okay cool Asian flank steak Philly cheesesteak you'll notice it took a while to like load we're gonna do like loading views and Spinners uh in the in a later video you know step by step here but you see our Network call is uh working properly let's walk through that refactor one more time again repetition is the

name of the game apologies if you don't like my repeating itself I feel like this really helps so when our appetizer list view appears it calls on appear view model get appetizers cool let's go to our view model get appetizers gets called it makes the network call when it gets that back uh it switches to the main thread because we're update we're updating appetizers which causes a

UI update which needs to be on the main thread so in a success case set the appetizers that we get back equal to our publish variable uh this an array of appetizers so when this changes it broadcasts its changes so somebody's got to be listening good thing we set up somebody listening uh in our appetizer list view right that's what the state object V model is we're listening to

that now so we got those changes our Advertiser list view is like cool that changed let me redraw it redraws the view and now it uses the viewmodel appetizers array that is no longer empty it has our actual objects in it populates all the cells we're good to go so hopefully that whole flow is is starting to click with you you know hopefully this is becoming review and repetition uh if not

it's okay uh you know this stuff took me a long time to learn it's all good that's why we're doing this that's why we're repeating this that's why we're getting practice but our Network call is up and running and in the next video yo we're going to handle those errors properly like I talked about so let's do it we left off last video refactoring our Network call into our review

model as you can see uh here well one thing we're missing is the error handling that's what we're going to tackle in this video you can see in the failure case we're just printing error.localize

description well in this case we want to show an alert depending on what error gets passed to our failure case just to recap back in our network manager remember we're passing the failure case right depending on what happens we're passing unable to complete invalid response invalid data

Etc that's our AP air enum you'll notice there's no like raw value like we did before remember that was only temporary all we need to know is like hey what was the case and then here in the view model we'll figure out like what we want the error to say We'll create that alert item and that alert context if you remember that from our barcode app we're basically going to do that same setup except

in this app it'll be built out a bit more because there's more screens there's more opportunities to show errors so you'll get to see us build upon that concept but the the basis is the same so that being said let's create our alert file so click the appetizers folder command n for new file Swift file hit next and if you remember we called this alert and this is where we put our alert item and

our alert context uh it's so similar in fact we're going to do a file open recent we're going to pull up our Barcode Scanner and copy and paste from our alert view here so pull up your barcode app come copy paste this just save some time some may say that you should maybe avoid doing this like I could see the argument for that because copy paste errors I've said it a few times in

this course they definitely are a thing but what you're going to find as you you know build more and more projects throughout your career is you're going to have a lot of the the same code that kind of gets shared uh you know maybe tweaked a little bit but for the most part it gets shared between projects this alert item is something that I've been using in all my Swift UI projects so let's

close out the barcode uh and just copy and paste it here into our alert and I wanted to show that because you know I just want to be transparent like that's how I legitimately work right like if I have to build even like my network manager again just being straight up like I don't type this out every time I have the same structure of a network manager and like all the apps that I make so when

I'm making a new app I'll literally copy and paste like the first chunk of my network manager paste it in and then make my adjustments and again I'm telling you that even though some may consider that a bad habit for the copy paste stuff but again just want to be transparent that's actually how I work anyway let's make the tweaks because like I said you can almost never copy and paste

and not change anything there's always some tweaks to be made one thing that I didn't do correctly in the barcode is I made the title and the message a string and if you remember in the barcode app I had to like go back and like oh I forgot I got to wrap these in a text to show the alert well

let's just you know take out that step altogether and make these texts instead of a string right so we'll make them text in our alert item you'll see how this you know benefits us and cleans up the call site when we implement this that's the first tweak we need to make the next week is you know these aren't our two errors right these are the errors specific to the camera from the barcode

app so this is what we got to change but to me the value of copying and pasting it is like I get the same structure right I just got to change the the names and then you know what the strings actually say so let's start changing this if I go to my AP error I see I have invalid URL invalid

response invalid data unable to complete okay so we're gonna create those here so I'll do to uh let me just make two more here to get all four of my my structure here okay so this first one again

was invalid data this was invalid response this was invalid URL and this was unable to complete and if you know me you know I like to uh get these equal signs lined up and not have anything look ridiculous there we go looks nice and neat and you know while we're here so this is what a

lot of people don't like about like lining up the equal signs like I do is sometimes it messes up your your um you know lining here and then you got to take that extra three or four seconds to line that up again I don't know to me having things be nice and neat and easy on the eyes to read is worth those extra couple seconds to line it up if you don't agree cool don't line

your stuff up no big deal I'm just giving you the reasons why I do it okay so I'm going to call these uh server errors so one thing to think about when you're creating these error messages right is oftentimes developers you know will make these error messages for themselves like if I said you know could not parse the data that means nothing to the user it means it means a lot

to the developer but you know it doesn't mean anything to the user so that's why you'll see a lot of these uh messages not really developer Focus right you want to focus them towards the user so you know you may not want to give all the details what's that supposed to say server error so here you know I would say you know the data received from the server was invalid please

contact support and I forgot about our new change here right we made these texts so again instead of string wrap these in in a text and right by doing it here I don't have to do it at the call site I probably should have done this before I copied and pasted so I don't have to write this out a bunch of times

okay so all I did was each title and message I just wrapped it in a text sorry to make it a text view not just a string so that's all I did during that fast forward typing part but okay back to our error messages again invalid response I'm just going to call this server error again they're all going to be called server error pretty much and we're going to say

invalid response from the the server please try again later or contact support and then invalid URL right like we don't want to tell the user like it's an invalid URL they might not know what that means so you'll say something like you know there was an issue connecting to the server

if this persists please contact support and look I'm not gonna lie I don't claim to be the the guru of error messages right my error messages could use some work we're keeping these generic but you know you should put some time into coming up with good error messages that really you know inform your user again I forgot this is server error and then server error that's the title of them

all and then for the unable to complete uh we'll do something like this unable to complete your rep request at this time please check your internet connection and I'm going to say that because most of the time when we get that overall error I get back to our network manager this is what fires it off the vast majority of the time that is because

there's there's no network there's obviously other ways to trigger it but most of the time you know the internet's down or something like that okay back to our alert so what we have set up here is our same old alert item from our barcode app and then we created our four alert contacts so this is the same exact thing we did in the barcode app just adding two extra errors okay so now that we

have uh our alert set up right we have the the item and then our specific alert context for the specific cases now let's go uh put these to use and we're going to go to appetizer list view model right where you know we're getting Network call and then we got to handle the failure case so as you see we're passing an error from the failure case like I said from the network manager

right we're passing dot unable to complete dot invalidresponse Etc so in our view model we can switch off of that error and show the right alert accordingly but before we do that I gotta actually create the alert item on on my view model so again this is exactly what we did in the barcode app at

published VAR alert item and that is of type alert item that we just created and it's going to be an optional and again it's published because anytime our alert item changes we want to broadcast that notify our list view that hey it's time to show that alert we're going to connect that here in a second but we have to make this alert item like a different alert based on what we get back from

our air right so okay let's switch off this error that we get back here so we'll do switch error in the first case will be dot invalid we'll say data or response whatever and the order doesn't matter here's how I do my switch statements I type the first case and then I let xcode say the switch must be exhaustive and I'm like yes xcode I know thank you for typing that for me I'm lazy

um so in the case of invalid response we want to do we want to make the alert item equal to alert context dot invalid response right so what we're doing here is we're tying the alert item to the alert context we created for invalid response which back to the alert here you can see for invalid response we're going to show server error invalid response from the server please

try again our contact support right so we're going to show this alert and you see reference to alert item needs self so I can do the Quick Fix here or what got introduced in Swift 5.3 is the ability to capture self up here uh that way you don't have to use self everywhere in your your closure here

right because each one of those would have had to have self next to it um but again new and Swift 5.3 captured up here and you don't need to use it again we still needed to use it here not to make sure we're referencing self but to differentiate between this appetizers right that's attached to the view model or the local appetizers and again that's because they were the same name if they

were named differently I wouldn't need the self here okay just a little clear that up in case you're confused so now uh we're just going to do some copying and pasting again because we're just going to set the alert item to different alert context based on what happens right so invalid URL again alert context invalid URL same thing invalid data now invalid data and unable

to complete is unable to complete and I'm going to let this breathe a little bit and have the two put a space in between these two cases and then each individual case I have a space this is just formatting uh again I think this is easier on the eyes easier to read rather than it being all clumped up um and you know if I only have two cases I'll probably keep them clumped up you know

the more cases you have the harder it is to read when they're clumped up so this is completely subjective styling I just want to put that out there but what we have set up when we did our failure depending on what that failure is we're setting our alert item to the alert contacts that we created so what triggers here is this alert item uh variable here will change that change is

going to cause this publish to say hey whoever's listening my alert item changed do what you need to do so we've set up the broadcast side of things we haven't set up the listener if you will so into our appetizer list view on our navigation view we're going to do the dot alert and again this should look familiar right you can do is presented we talked about this last time that's just based

on a true or false variable that you pass in but we want to have this alert be triggered when an item changes that's what this item content is right and The Binding needs to be identifiable but that is our dollar sign viewmodel dot alert item right and remember our alert item here does conform to identifiable we talked about that in the bar code video it's back to our appetizer

list now the content we need is our alert so we can do Alert in and now we do capital A for alert and initialize a new Swift UI alert and just like before we're going to do title message dismiss button so the title is now alert and we're actually going to change this name to alert item

just to be you know real clear on like what we're talking about here so alert uh item dot title and now this is where last time I had to like wrap this in in text you know I messed that up well now because we put that text in our alert item we can just keep it neat at the call site and just do

alertitem.title same thing alertitem dot message and then alert item dot dismiss button now quick

alertitem.title same thing alertitem dot message and then alert item dot dismiss button now quick disclaimer on how I'm doing these alerts this is for the basic alert that just pops up and you hit OK to dismiss right if you had an alert that had like maybe two options or two or three buttons that did something on the buttons you know you can't do that we have to create a whole new thing

which will get to you know later in this section but uh you know majority of your uh your alerts are going to just be okay to dismiss type stuff so it's nice to have that you know structure okay so we should be all connected here let's uh run it on the simulator I'm going to run it first uh you

know nothing should happen this should look like it's been looking and yep here we are this is what we had before nothing has changed uh all we did was mess with the alerts but I wanted to show that real quick now let's start messing with things to break it like on purpose so going into our network manager um let's put a let's put a nice little Emoji in our our URL right because what's going to

happen here is URL is going to try to initialize a URL object from the appetizer URL string remember I said this returns an optional because if it can't create a URL object it's going to return nil so what's going to happen with our Emoji here it's going to be an invalue url url is going to return no so we should go into the invalid URL alert let's see here let's test this there it is okay

yep server error there was an issue connecting to the server if this persists please contact support cool all right let's just try one more let's get rid of that let's turn off our Wi-Fi here uh if anybody gets the reference to this wi-fi leave it in the comment uh kudos to you if you get that um okay so let's run it again with the Wi-Fi turned off foreign server error unable to

complete your request at this time please check your internet uh connection okay so our errors uh seem to be working let me turn my my Wi-Fi back on okay so our ears are working one last overview to finish out the video again our Network call passes in various errors depending on you know what happens here in our alert we created our alert item uh we have our alert contacts for all

the various different errors that we could have in our view model on our list view right depending on the failure case what gets passed back we make our alert item equal to whatever alert item you know is applicable to that specific error that sets this alert item and because this is published on our observable object of the viewmodel it broadcasts it out our appetizer list

view is listening to that because we have our view model as a state object so here in our alert this viewmodel.alert item has changed this alert is listening to that change so when it receives that

viewmodel.alert item has changed this alert is listening to that change so when it receives that change it presents uh the alert uh with the title message and dismiss button based on the alert item that we passed that's the overview of what's going on to show those alerts so the base six of our errors are in place we're going to be building upon this uh you know in future videos and in

our other screens but this is the basics that was a bit of review like we did a lot of the similar stuff in the barcode but again practice practice repetition repetition repetition let's move on in the last video we got the foundation of our alerts in place in this video we're going to implement a loading spinner screen you know for when the network is slow and you want to let the user

know like hey you know this screen is loading now as of iOS 14 there is no Swift UI native spinner view uh if you're watching this in iOS 15 or iOS 16 I bet this is going to come pretty soon seems like a pretty obvious candidate for something to get in there quickly but for now we still have

to go down to UI kit which means we got to do UI view representable I didn't say UI view controller representable UI view representable so it's basically the same thing but a small little tweak that you'll see here okay so in appetizers here command n for a new file we'll call this loading view because we're going to combine our UI View representable and the actual loading view because

it's super simple in the same file and I'll tell you why when we're done here so again loading View hit create we need to import Swift UI for sure and we want to create a struct called activity indicator and this is going to conform to UI view representable because we don't need a whole view controller we just want this View and then just like last time it's going to say we will not

conform so hit fix remember last time we had to do the type Alias what type of UI view is this going to be it's going to be UI activity [Music] indicator view that you see right there and then now in a command B remember this was like the the two-step process now it's going to say I don't

conform hit fix cool now I get the uh the protocol stubs that I wanted with the uh it returns UI activity indicator view it has my update view all filled in with the type so now we can get rid of the type Alias again I'm going quick because this is review I think we've done this three times now again the only difference is it's just a UI view representable not a UI view controller

representable so again the update UI view is just an empty implementation but here in make UI view just like last time we had to actually make our UI view controller well now we're going to make our UI view so let's say let activity indicator view equals UI activity indicator view we're gonna initialize it with a style and the style we want is dot large right you can do

it with DOT medium uh it's fine we're going to dot large we want this a nice big fat spinner here and then we can customize this a little bit more we want to we don't want to make it gray we want to make it our green color our brand primary color so I can do activity indicator view dot color

equals and you see we had color with the name now here's where we're going to fix this real quick right because I don't want to have to type out brand primary every time if I have a typo it's not going to work right we don't want to keep repeating these strings so right now well let's actually finish this so xcode doesn't give me errors activity indicator view dot start animating

right so when this gets created it's going to start animating and then return activity indicator view so again all we did was we created The View here with a large style we set the color and as you're seeing my error right we're in UI kit right UI kit just doesn't have color right it's got to be UI color and then UI color has to be you know named with the string right so anyway we're going

to fix this right because I don't want to type brand primary and then we uh animate the activity indicator and then we return that right remember the make UI view or make UI view controller is what replaces the body variable on our view right just to be clear about that so now let's go refactor our color out a bit so again click on appetizers uh command n and we're going to do

project organization soon because you can see this is starting to get uh ridiculous let's call this color plus EXT we're going to build an extension on for color and that's how I usually name my extensions you know whatever the the object is plus EXT and then I usually have an extensions folder again project organization coming soon so let's import Swift UI and we're actually going to

do this two ways we're going to do an extension on just color right just color remember is the Swift UI color not the UI kit color and remember we're in UI kit currently for activity indicator so our extension here we're going to say static let brand primary equal and then we're going to initialize a color with the name brand primary and then here we're going to do another extension

on UI color this just color covers our you know UI kit bases and basically the same thing just the UI kit version static let brand primary equal UI color and then just like we just did right named and we'll copy and paste this just to make sure we don't mess that up here so named brand primary

do it command B make sure we're good okay so now if you remember in our uh tab view appetizer tab View Way Back in the beginning we did accent color brand primary and now we can fix this and change that but to be sure let's search for it right let's be safe here so hit this search button in the finder we're going to type brand primary just to make sure we get them all

right so appetizer tab view that's the first one cool so instead of color brand primary we're going to do dot brand primary right because we made an extension on color now it's much easier and nicer to read so assets cool I'm not going to change that loading view right okay cool instead of UI color uh brand primary we can do UI color dot brand primary to get that color now and where else

do we have okay in our extension yep that's where we just created it okay cool so we have all the instances of brand primary now refactored into you know the colors right and you would do this for a lot of the colors you use in your app brand primer is the only color we're going to use now but that was a little little side Adventure on refactoring out our colors so now that we have our activity

indicator all set up formatted ready to go now I just need to use this activity indicator view in some sort of view that we want to present when we're loading okay so we're going to create that right here and this is what I meant by I'm gonna I keep these in the same file so we're going to

do struct loading View and that is confirm to view right now we're in Swift UI right now so that is a VAR body of some view okay so now that we're just a typical Swift UI view setup we haven't returned anything yet so it's yelling at us so what we want in our loading view is just a white screen in in

light mode a black screen in dark mode so we're going to use system background as the color but so we just want that as the background and then the spinner on top of that so we're going to need a z-stack right the the bottom of the Z stack is our color background on top of the z-stack is our

spinner okay so Z stack and again the bottom is the color and we're going to do uh dot system [Music] background so again system background will be white in light mode black and dark mode and we do want to make sure we do dot edges ignoring safe area dot all because if we don't ignore the safe area our background's not going to go up to the status bar and it's not going to go to the

to the home indicator at the bottom so we want to make sure we fill the entire uh screen okay so that's the the base layer of our z-stack so on top of our z-stack all we got to do now is just do activity indicator right and create a new activity indicator View and that's it for our loading view again the background color activity indicator on top when this gets called it's going to call make

UI view which is going to initialize this activity indicator view with a style of large we're going to set the color to Brand primary and we're going to start animating okay great now let's uh use this loading view so in our appetizer list view here I now want to make this entire thing a z stack and the reason being is because uh I want to basically put my loading view on top of everything

when it's loading and then remove it when it's not okay so wrap this in navigation view in a z-stack and then I'll copy and paste this whole navigation view command X command V Let's just say cut and paste not copy paste and then I actually want to move this alert onto my Z stack I want that

to be on the uh the root view if you will before navigation view was the review now the Z stack is okay so if you look at our Z stack remember the z-stack is the the layers The View hierarchy well right now the bottom layer of our z-stack is our navigation view that holds the list well what I

want to put on top of that is the loading view but only when it's loading so I want to do something like this right like if is loading uh now I show my loading View right and that way if it's not loading the loading view never shows up so I need this this Boolean of is loading okay so let's

go to our view model to put that on because that that relates to our Network call correct so back to our appetizer list view model and we really need to organize this stuff I'm having trouble finding that again soon uh so okay so here is our Network call right this get appetizers okay so we know we need to work with this well first I need that is loading uh Boolean so at published right

because we want to we want to let our appetizer list view know when this changes because we want to you know redraw so VAR is loading and that is a Boolean now we'll just say equals false for right now because right the default state is we're not loading uh it equals false so before we go any further right we created that uh Boolean uh back in our appetizer list view uh here we have

it now except it is viewmodel dot is loading okay so now we're good we've connected that now we just need to go back to our view model and actually flip this Boolean at the right times Okay so so basically as soon as we call get appetizers we want to set is loading equal to True right so as

soon as this function gets called that's going to get flipped to true and then what's going to happen on our appetizer list view is this is going to get redrawn we're going to go into this if statement because now we are loading and then our loading view is going to show and it's right on top of the Z stack so just imagine like our loading View getting smacked on top of our list

that's essentially what's happening and then what's going to happen here back in our view model we need to flip this to false when we're done loading so when are we done loading here in our when we're going to the main thread because this triggers a UI update so we want to make sure we're on the main thread for this we can do is loading equals false and this is basically as

soon as we get back a result we don't really care if the result is a success or a failure we're done loading right whether whether it was good or bad we're done loading so here we flip this back to false and then again what happens is this changes it publishes its change in our appetite list view this is going to say okay cool is loading is now false it's going to redraw and then it's not going

to go into this if statement because is loading is false so therefore our loading view will not get put on top and you won't see it okay hopefully that all made sense let's see this in action so run it on the simulator you're probably not gonna not gonna see it because it'll be too fast okay you saw for a split second now let me use my network link conditioner if you don't know

what that is I'm not going to derail this video and teach you how to do that I just did a video on my YouTube channel recently I'll link to that in the description because many of you may already have this but in your system preferences uh here next to my Xbox 360 controller at my network clean conditioner and this is basically I can turn it on and you see very bad Network and you see my little

menu item up here this tells me my network link conditioner is on so basically I'm I'm slowing down my Wi-Fi intentionally so I can test you know bad network connections so let's run this again and test the bad Network you'll see how slow this goes with my network link conditioner right so there's our spinner it's going for a while because our Network sucks you know we're simulating that

maybe you're in a spot you don't have to simulate that who knows but now you saw our spinner in action and you can see that flow that I talked about I'm going to run it one more time right as soon as we call get appetizers it redraws and our spinner shows and then as soon as we get a result back from those git appetizers you know our variable gets published we listen to that we

see the change we redraw again and we don't show our loading screen so now our basic loading screen is in place that wraps up this video in the next video you see all these Asian flank steak images we're going to start downloading these images from the server and populating the correct ones we left off last video getting this simple loading screen in place in this video we're going to implement

another Network call to download the individual images of our appetizers so back in xcode just to refresh real quick if I go to my appetizer model right we have this image URL that is a string right so the the data we get back from Json has a URL attached to it and that's what we're going to use to download this image but the first thing we got to do is into our network manager we have

to create another Network call similar to our git appetizers now the concept for this network call is the same however we're going to handle it a bit differently and the reason being is looking at the design like we want to show a placeholder if something goes wrong with our Network call or if there's no image right we don't want to pop up an alert to like bug our user every time like

uh an image goes wrong right because you see all the images on this screen like you'd be popping up alerts that's just so annoying so our way of showing an alert when an image goes wrong is just showing the placeholder right just kind of it's almost like failing silently except you have that placeholder anyway we're just not bombarding them with alerts so that's why this network call

is going to be a little different because this is our git appetizers Network call right you see we had to check for the air check for the response check for the data because we wanted to give specific errors uh for each case well in our Network call to get the image we're not worried about specific errors so you're going to see this uh get get simplified a bit okay so let's

write this so I'm going to scroll down here create a new function Funk download image I'll move this up a little bit and we want this to be from you URL string right because we're going to pass in a string here and the reason I like to be specific like this like say hey it's a URL string is to just differentiate between when I'm expecting a string or what I'm expecting you know like the

URL object so that's why I like to do that little little tidbit there so it's going to take in the URL string again that's what I showed you it's the URL attached to the appetizer and we're going to have the completion Handler completed which is an ad escaping uh closure I don't know if you had a chance to go review that on my YouTube channel that I linked last time but if not you should

definitely check that out and then here's where it's a little different I'm going to scroll up to compare right last time at this part we returned uh a result that he either had an appetizer or an heir remember because we wanted to pass back there well I guess I'm going to copy this for format purposes so command C uh command V so uh initial just also illustrates the differences here so we

don't need a result type because we don't care about the failure case remember we're just using the placeholder all we want to return is a uot the UI image and is telling me it doesn't know what a UI image is because if I go up to the top I have not imported UI kit side note UI kit automatically Imports foundation so you don't need both to command B so now I have UI kit now it knows

what a UI image is however uh like we talked about there could be an error case so UI image could be nil we're not always going to have a UI image so let's make it an optional uh with the question mark and then let's create our open and close brackets for the scope of our function so again that's our function signature you know we're going to do networkmanager.share.downloadimage

we're going to pass in a URL string and the completion Handler is either going to give us a UI image or nil based on what happens in the network call now one thing we're going to set up for our images is the cache right like we don't want to always download our images repeatedly as we're scrolling up and down uh the screen so we want to put those in the cache for fast scrolling

and you know we'll check to make sure it's not in the cache then we'll download it if it is in the cache we'll just yank it out of the cache and then use that image without even bothering with the network call so that's what we're going to set up now so to do that we need to set up our cache up

here so private let cash equal NS cash and we've got to use NS because cash is still pretty old school so NS string what we're basically putting in here is the key value pair that we expect in our cache I gotta initialize that so basically what this is saying is our identifier is going to be a string or an NS string and at that identifier in the cache is going to be a UI image so we're

kind of telling our cache what to expect to store okay so back in our download image Network call this is the first thing we want to check right again before we mess with making a network call let's make sure it's not in the cache first so we're going to set up a variable for a cache key and this is just a quick way to reference it here remember the key is this NS string right here and

the key we're going to use is the actual URL address because that's pretty unique right you want your keys to be unique so that's going to equal an NS string from a swift string down here and that string is going to be from URL string that's what we're passing in here and you know what that naming can be better uh quick tip here on like argument labels versus parameter labels

so I can say from URL string will be what shows up at the call site and if I just do space here URL string that's what shows up within the scope here so I don't have to say like from URL stream everywhere I can say something that makes a little more sense you know a little more readable it's just URL string not from URL string small Minor Detail but you know it does help especially when

your scope is really long and you're using it you know it just makes more sense so here we have our cache key which again is just the URL that is attached to our appetizer that's a unique string to identify the image so let's check our cache so if let image equals cash dot object for key right we're going to go you know whatever object is at this key in the key we created was cache key

so if we have an image cool we're going to call completed and pass in the image right we're going to fire off our completion Handler because we have an image there and then let's hit the old uh return and we're done here we're out of the function we're not even going to like mess with the network call however if you know we check the cache and we get a nil it's going to continue on

and now is where we need to make the network call to download the image because we don't have it in the cache so now's where we have to do a similar check right we want to make sure our URL uh is is fine so guard let URL equal URL string else and completed nil and then we return we're out of here

uh we're just going to show the placeholder images okay that's the same URL check we did before now let's actually start creating our data task this is where it gets a little different but this first part's the same so you know what we're just going to do a copy and paste so I don't mess that up and type it like I said I do the copy and paste on the same stuff like uh quite often

what I mess up here regardless URL equals URL string else completed oh we're not just checking against the string we're checking against the URL initialization uh of the string remember because when you initialize the URL object it can return nil if the string is invalid so yeah forgot to do that part we're not just checking the string and then down here I need a closing bracket to finish

that off Okay cool so we have the same setup that we did before remember we get back data response and error well remember this is different we don't care about the errors right we don't have to check all this all we care about is did we get back good data so that severely limits our checks here so I

can do guard let data equals data and then I can uh you know combine another one here and say let image equals UI image if you're not familiar with this I'll walk through it afterwards we want to initialize the UI image from data and then that's the data that we got and then else so if we don't

get any of this we're going to call completed uh nil and then return so what's going on here is I'm saying hey if I have good data great now keep going if I have data let's try to initialize an image from that data now when you initialize a UI image from data that can also return nil that's why we're unwrapping this so either we have bad data or trying to create an image from that data

if that returns nil we're going to call complete and nil if we got good data we were able to create an image from that data we're good to go let's keep moving so now we have our image so we want to do two things right we've downloaded the image so let's put it in the cache so we don't have to download it again next time and then let's call our completion Handler with our image okay so

let's do that so self dot cache dot set object for key right so now we're saying hey whatever's at this key make this the object in the cache so the object we want to set is the image that we just you know created from our data up here and then the key again is cache key which is essentially

the uh the URL string that we're passing in so this line of code sets the item in the cache now we want to call completed with our image not nil right and that's what's going on up here in our completion Handler right passing back an optional image now we actually have the image so we're good to go this would be like the success case and then the last piece as always the one that trips

everybody up task got resume did I mess up the scope again nope I didn't all right so let's clean this up again do a command B to get rid of any warnings or errors or see if we messed anything up nope I like two spaces vertical spaces between my functions just me all right so let me walk through this high level one more time before we wrap up this video so you understand the network call

right we're calling download image we're going to pass in a URL string which is the URL attached to our appetizer view this network call is going to return a closure that's going to either have a UI image or it's going to be no right it's optional we're going to return nil if things go bad we're going to return the image if things go good right now we want to set up our cache and again we did

that up here with the cache and you see the cache takes a key and then the object it's key value pair so the key is going to be a string and we're going to use the the unique URL for the image to be the key to identify it so we create that cache key from that URL and then here's we're checking

our cache to see if we have that object before we download anything right so if we have the object cool call completed return the image we're done good game right if we don't have the image in our cache all right now we got to download it so now we check to make sure our URL is good make sure nobody's given us any funky URLs cool if the URL is good now let's create our Network call here

remember the network call returns data response or error in this case because we're just showing the placeholder if things go wrong we don't care about the errors so we don't have to do all these other checks we did before we can just see if we got the good stuff right so guard let data equals data did we get good data and then if we do have good data cool can we make an image out of that

data if we can't you know complete a nil show the placeholder we're done if we can make an image out of that cool set that image into the cache so we don't have to download it again next time and then call the completion Handler to pass that image up as the success case and then task.resume is what actually fires off the network call so we're going to stop here on this video just to set up that

Network call but in the next video we're going to create our custom Swift UI image that can download images remotely so let's do that we left off last video creating our Network call now let's put that Network call to use okay so in appetizers and I promise the next video is Project organization so we're gonna clean this mess up over here uh one more file so command n for new file new Swift file

hit next we're going to call this remote image we're actually gonna have a couple objects in this file because it's I find it easier to keep this all together rather than separate less confusing okay so we definitely want to import uh Swift UI and now we're going to create a couple of objects like like one is an observable object similar to a view model but like not the same um that we use

with our custom Swift UI image so this is going to be multiple puzzle pieces working together so as we build this out initially you may be like uh what's going on but you know as you've seen in all these videos at the very end I walk through it to connect all the dots for you to hopefully help you understand so if you're a little confused while we're building this out don't worry I gotcha so

the first thing we're going to create is our image loader which is that that class so final class image loader and this does conform to observable object because we are going to have a property of an image of our image that is a swift UI image and for right now it's going to be optional and we're going to give it a default value of nil so what this image loader does is it actually

downloads the image and then it broadcasts hey I've got my image right just like the The View model does right it broadcasts its changes so in order to do that I got to make this published right because we want to know when this image changes and this image is going to change when we have a successful Network call so now we got to make that Network call here so we can do Funk load

from URL string and again similar to what we did we're just going to call this URL string and that is a type string a lot of strings there and then here we call network manager dot shared dot download image you know from URL string well that's going to be the URL string that we pass in here so URL string and then the completion Handler is going to be image and then we get rid of the

parentheses now remember this image is optional so we have to handle both cases if it's nil or if we actually have an image and we're going to handle that no case first so guard let in okay I messed up the naming we actually want this to be UI image just for clarity as you'll see in a little bit because we're going to be talking about Swift UI images and UI image so we don't want to get

those confused so we want to be very clear that this is a UI image so I messed up my naming so we can guard that UI image equals UI image uh else and then we're just going to return here so we're going to keep that on the line else return because again we're not handling the errors we're just showing the placeholder if things go wrong so now that we've unwrapped the optional like we know we

have our UI image we need to set this image here uh the Swift UI image to the UI image hopefully that wasn't confusing maybe this will maybe this will help you out here so we do self.image equals

and we're going to initialize an image this is a swift UI image not the UI image but an initializer on the Swift UI image you'll see I can initialize one from a UI image right and that's the UI image we have so this is why I wanted to be clear and name this uh UI image and not image to be

confusing right I wanted to definitely uh separate the two now again one thing that trips people up remember yes we're just setting the data behind the scenes here but because this is published it's going to trigger a UI change right because once the download is successful and we set our image equal to the actual image we have we're going to redraw the UI and show the downloaded image

so because this triggers a UI change we want to dispatch this to the main queue so dispatch q and by the way I just tried it so I don't have it on this machine but on my development machine my laptop I have a code snippet right just type DQ and it types out dispatchq.maine.async because you type this so often so a little tip there if you want to create a code snippet I would recommend

that so command X command V to paste that in there so now we're updating our image on the main thread to trigger the UI update okay so that's the first piece of the puzzle this image loader is what downloads the image the second piece of the puzzle which is kind of just like a helper for the final piece and I'll it'll make more sense when I get everything together it's going to be a

struct it's called remote image and it's going to be of type view and now we're now in just a regular Swift UI view here and a property on here is going to be VAR image and is of Swift swift UI image but it's going to be optional because again it's going to use this that returns we may not

have it right if the network call fails we get a nil so we got to make this optional and then here we're going to have our body some view this is just the the standard initializer you know for Swift UI and here we're returning uh this is where we want to return an image like a swift UI image

so if we have image we're just going to return what we got back so image and it's an optional we'll call Dot resizable because dot resizable is one of those custom modifiers that can only be called on an image that'll come into play later but just remember this is why we have to call resizable here so if we have the image cool just you know the remote image is that image however

if it's nil we don't have it here's where we want to return an image except the name here is food Dash placeholder and I just realized we forgot to bring this in so I'm going to bring this in this file of course will be attached below the video but I'm going to drag this into our XP assets so

we have it so if I go to my finder here I get it ready I see these are all the images here's my food placeholder and then we'll drag that let me open up XC assets go back to finder drag that into here and hopefully you do the same thing and then you get this nice placeholder image that will

look good on both light and dark mode so now back to our remote image that's what we're going to do if we have an image that's returned nicely from the network Hall show that give it the resizable modifier if we don't if we have nil show the image with the food placeholder also dot uh resizable so that is puzzle piece number two and it's really just the helper for puzzle piece number three

because if you don't have this helper you'd have to write some pretty convoluted code and confusing code in in the third puzzle piece so we're going to write that right now and this is actually what we're going to use in our you know usual Swift UI code this is going to be struct we're going to call this appetizer remote image and is of type view and again it is a typical Swift UI view

so we want to do VAR body some View and get that all set up now this is gonna have two properties we want a state I'm going to scroll up here my head's probably getting in the way State object VAR that is a image loader right this is what we want to have attached that we're watching this image loader right so of our image loader and that equals and a new image loader we're initializing a

new one here and then the other thing we need is a URL string right because we when we create this appetizer remote image we need to know what URL to load from so let URL string and that is I'll type string so that's what we're going to pass in based on you know what appetizer we have okay so now here's where this helper comes in right we're gonna for our body of our view we're just

going to return a remote image right that's what we have here up here and the initializer for the remote image if you saw that takes in an image which is an optional image so what we want to pass in here is the image that's attached to our image loader right remember this image that gets returned after the network call is done so right away that image is going to be nil but after the

network call you know finishes successfully it's going to make this image no not new it'll make it image this will broadcast the change our appetizer remote image because we have this set up here as a state object is listening for that change and then it will redraw and create its image you know with the image we have here so I do image loader dot image all right so I'm initializing

this remote image with whatever we get back from the network call or the placeholder until we get anything back now uh you'll notice when I just draw this once imageloader.image is is nil so I gotta I gotta trigger the network call somehow so when this remote image appears so we'll do on up here and put the closure afterwards so when this image appears I want to call Image loader

dot load image from URL string and what URL string do I want to load from well whatever we passed in based on the appetizer we have from URL string put a space there and we'll remove this space okay so like I said here are the three puzzle pieces I know I've kind of walked through it as I've gone but I understand this may be confusing so I'm going to do one more I'll walk through now

that we have all the pieces in place and hopefully it'll make a little more sense so this appetizer remote image is what we're going to use like on our list view to replace our just regular image placeholder and what happens when this appears on screen right because on appear happens well when on appear happens we call imageloader.load remember our image loader we have attached here

as a state object right so it's attached to our view well the image loader is going to call load it's going to make the network call if the network calls bad it's going to stay nil right so we're going to show the placeholder if the network all is good this is this image is going to flip to the good image because it's published remember it broadcasts the change our appetizer remote image

is going to see the change and say okay I gotta redraw and now when it redraws it initializes our remote image with an image and it's going to use the image loader.image well what is our image loader.image now it's no longer nil because we had a good Network call it's going to be

loader.image now it's no longer nil because we had a good Network call it's going to be the actual picture of mozzarella sticks so that's what we're going to show so that's how this little puzzle piece works and again the remote image is just kind of a helper to make this code kind of clean you'd have to write some pretty weird stuff I tried I couldn't get it working it was weird so

the helper was was nice um so that's kind of what's going on here now let's put it uh into play here on our appetizer list View and then test it and see if it works right we've been coding for two videos without testing let's see if this works so I'm sorry not our appetizer list view our appetizer lists sell right and what we want to replace here I'm going to pull up the canvas

minimize it there a little bit hit resume should pop up okay previews am I right never mind get out of here we're good this is by the way I just downloaded xcode 12.2 the other day so maybe that's why it's taking longer anyway uh we just want to replace this remember this generic image we had that was just the Asian flank steak all

the time it's kind of our placeholder well now we don't want that image we want our appetizer remote image and when we initialize that right that takes in a URL string and the URL string we want to pass in is our Appa Tizer dot image URL right and you'll notice remember this is what I

said resizable is one of those modifiers that can only go on an image well even though our appetizer remote image like you know is basically an image we're doing some other stuff to it and it's not just that raw image that's why going back to that remote image like that's why we had to put resizable here because this is actually on the image right so we're handling the resizable stuff

you know abstracted away so on our actual cell here we can just delete the resizable because we're already doing that and you see we even if we wanted to do it here we couldn't because that only goes on to an image so do command V get a build should be good to go all right moment of truth last time this didn't work out so well again I haven't tested this I'm just building it now so

first time let's see if this works bam there we go nice no more embarrassing debugging on the Fly even though I think it might have been helpful but yeah so you see we have our images here we're no longer just looking at Asian flank steak we're pulling up the proper images uh for each appetizer now let me break this down again real quick so we'll stop this we'll pull up the network

link conditioner turn this on uh this is just a valuable tool if you didn't bother to set it up last video or last time I showed this go do it it's very valuable so I can show you what's going on here so I turned it on I'm on very bad network uh now let's run it again and you'll see kind of

the process here slower first of all we get our spinner that's fine we're going to get back all of our Json for that and you're gonna see the images start slowly loading in right so you can see we're showing the placeholder until we get the proper image and I'm scrolling up and down real fast to show you that you know we're still getting the proper images um but uh yeah so you can see while

the uh image loader image is nil we're showing the placeholder wow this is really bad there it goes uh so here we're showing the uh final image once it's finally downloaded so hopefully slowing down the network connection showed you the process because it happens pretty fast um I have Google Fiber here weird Flex I know but anyway our image loader is in place uh that wraps

up this portion our our list is looking good in the next video we're finally gonna tackle this mess over here and start organizing our project we left off last video downloading these beautiful images that you see here now we're going to clean up this Rat's Nest that is our our files right and you know maybe you want to challenge yourself organize it yourself real quick um I'm gonna

follow basically the same Organization principles that I've been following uh so it should be a little bit of review but again organization subjective if you have a different way cool uh again more practice doing it my way so uh new group here so the first thing we're going to start off with is the screens kind of like the the heart of the app I did new file I did command

I'm so used to doing command n right click new group um we're going to call this screens and okay so the screens we have right well I'm going to create a new group in here before I start moving stuff right I want a Appa Tizer list view okay cool now I want a folder new group for account view you can see I'm I'm basing this uh based off of the new group

um the tabs on the tab bar right and then we have a order view right because again when you're when you're organizing the project I find this easier right especially if a new developer comes in that's not familiar you know and it's broken up by the tabs it's a lot easier to like navigate and know what's going on so that's how I like do it and then I do like to have them kind

of in chronological order right appetizer not in the folder that's one thing that gets tricky sometimes it's finicky right so appetizer account order view cool what goes in the appetizer list view well that's our appetizer list view that's one our appetizer list view model that's two and again I like to put my my view model on top and then let's take our account view into our account

View and then I like to open up the folders just to confirm you know things are where I expect them to be and then the order view cool now I'm going to create in appetizers my utilities folder right remember I said this is kind of kind of like a catch-all and it can get out of control but I think if I have sub 4 Builders I think it's fine some new uh group here I call this

like managers because usually there's a couple like a session manager managing the user network manager there's a couple of these so back in utilities new group now let's add extensions okay now let's start organizing this a little bit so network manager goes into managers uh where's my color extension color extension it goes into extensions okay let's create a

new folder uh new group I don't always do a separate folder for this do uh alert and you know I can probably put my my AP error and my alert in that folder I thought about naming it like errors and alerts but I don't like super long folder names um so those kind of go together so now what are we missing um The appetizer.tab View it's kind of like the overarching thing I put this

in screens at the top I don't put it in a folder though right so you see my screens folder has the app tab View and then the screens I kind of like the way that looks again completely subjective of course we're going to need a new group we need a model folder for our appetizer and then you know some future other stuff so appetizer.swift move it into our model you see and I'm kind of just

going down the list right so loading view I'm going to put this in my uh my UI kit components because like I said I fully expect an activity indicator to be native to Swift pretty soon um I'd be shocked if it wasn't like in the next major Swift update so we're gonna put this in UI component UI kit components and the reason I like to keep that separate is because I know

exactly what to go in and replace as Swift UI you know evolves and gets all this functionality so let's minimize my folders to look at my overall structure real quick so model utilities screens so again this is where I start doing the views folder so new group call it views and this is kind of like overarching because there's a lot of different views especially in Swift UI so the

new group in here will be UI kit components and then the other one will be cells you see my appetizer list cell new group call it cells and then remote image so we'll call this uh new group call this uh image okay so let's just drag this here cell goes into cells loading view goes

into my uik components and remote image goes into my image so and then I usually like to have views down here above screens so I like to have like the stuff like the model utilities all that kind of stuff I like to have at the top and I like to have my views and my screens the stuff I use the most at the bottom I understand that sounds kind of backwards that's just my preference but

you can see the folder structure right model with the appetizers utilities we have alerts extensions managers in my utilities views images cells UI kit components screens see it's broken down with the tab view by Tab and then of course you know as these get more complex these can have subfolders as well so I've said it a thousand times and I know but organization is subjective

just take what you like for me leave what you don't come up with your own system just try to put yourself in the in the shoes of somebody new coming into your code base and not knowing your special cool little system like I try to keep it the most logical and obvious as possible at least that's what I strive for that's what I think you should strive for too when organizing your project

now that we've got our project organized let's shift gears a little bit and start building our details screen right as you see in the design this is what pops up when we tap on the table view we see this details screen it's kind of like a card with some information about the appetizer and you know what it's challenge time again I encourage you to try to build this on your own now this

is probably the most complex piece of UI like we've done yet so if during that challenge you know you struggle don't worry it's fine that's what we're here for we're here to learn but you know if you've been skipping over my challenges so far I highly encourage you to not on this one right like just watching me type and typing what I type yeah that's cool but you know you're really

going to learn when you start to to push yourself and and do this on your own and try and figure it out and use what you've learned to build this now before you do this challenge a couple things of notes uh some things that are just different than what we've done before just to give you a heads up so you're not banging your head too much as you can see in the design right we're not designing

a whole screen we're designing like a little card so keep that in mind also the Blurred background over the list don't worry about that that's not part of this view that's part of the list view when we present it so don't worry about that and then there's one piece that we haven't touched on yet and that is the overlay modifier and that's what we use to build the little circle

dismiss x button in the upper right hand corner so just a little heads up on that if you do try to build this on your own okay so now's your last chance to pause if you want to try that challenge yourself again I highly encourage it if not oh well we're about to get going in three two one

all right here we go looking at the design let's break this down right so we have our overall card which is our view right that's just going to be a v-stack right we're going to give it a a background color of that system background so it shows appropriately in light or dark mode we're going to give it the rounded Corners that you see on the card and then we're going to give it a drop

shadow so that's like the basis of our card it's just our overall v stack and then the way I like to break this down is I like to break it down into main UI elements now quick disclaimer the way you do this is kind of subjective like there's many many different ways to skin a cat so they say I

don't even know where that came from from but uh there's a lot of different ways you can lay this out I'm just going to show you how I think about it if you like it use it if you don't like it you know figure out your own way that's better cool but how I do it is I like to break it down into

major like chunks of UI right so the way I look at this I look at the image that's a major component all this text like the title the description the nutrition information to me that's another chunk that like text information chunk and then the third chunk is the the button at the bottom so I have three main UI elements in my v-stack and then of course you know the text in the middle you know

that's broken down into another v-stack with my title my description and then the H stack which has a v stack inside it you know with the calories and then the number so that's just how I look at like a complex UI like this is I break it down and maybe chunks is not the uh you know the technical

term but that's what I call it you know just the major UI components and then I break those down like even further so that's how I tackle something like this so that's the overview we're going to be revisiting that design throughout but let's get started started here right so in our appetizer list view or tab right I'm going to do command n for a new file Swift UI View this is going to be

our appetizer detail View hit create cool here we are and then the first thing I want to set up before I forget is like I know I'm going to need an appetizer on this view so I can do let APA Tizer of type Appa Tizer and then we're good to go there we're passing that in of course our preview

is going to say hey you need an appetizer and just like before we did mock data dot sample appetizer and let's actually pull up the canvas for this one because we're going to be building this as we go here see if previews give us a headache again my usual routine there make it smaller all right cool so the first thing we want to build is our overall v-stack this is the

this is the card that we're going to build so let's get that structure going first so v stack now for right now let's just put a text in there just to give it something uh to show hello just so we can see it on our preview but now we're going to start um you know adjusting this to

make it look like a card so the first thing I want to do is give it a frame with the width and height all right so the width is going to be 320 and then the height 525 and then we don't need an alignment so you can see the red outline on our preview that is the the general size of our v-stack and

I chose 320 by 525 because that's going to be a good size on phones we're not worried about the iPad right now you know this is an app that you're going to use in a bar or a restaurant to order appetizers so we're just worried about the iPhone for now so you can see the general structure starting to take shape the next thing we want to do is give it a background color but

this is going to be color now I see it's blue just to show you what it is but we want to dot system background so again this is going to be you're not going to notice it because it's going to be white in light mode black and dark mode but again when it's over the Blurred background like you see in this design you know that's how we get this look so now we want to give

it a corner radius of 12 right to give it that rounded Corners again you still can't see it now let's make it so you can kind of see it by giving it a drop shadow we haven't done this yet um drop shadows in UI kit were always kind of like a pain but uh they're pretty easy in Swift UI you

put the modifier of a shadow and give it a radius of 40. you can add a color but the default is the black color that we want so we're not going to mess with like adding a color but if you did want like a Red Shadow you could do that so let me click uh on the overall screen to get rid of

that red outline now you can see the structure of our card and like I said because the background color is system background once we put that drop shadow on it it really makes it pop so now let's start uh filling in our v-stack with the three major chunks right I talked about the image the information piece all the text and then the button at the bottom and again this is how I build the

UI I break it down you know by components like that so first thing we have is an image and then the name we're going to use is our dummy data here XC assets the Asian flank steak copy that paste it into there and there you go now as usual with our images doesn't look right uh right away we gotta make some adjustments right dot resizable hopefully this is review by now

okay so see it resized it to fit that's not what we want uh we want to do aspect uh ratio content mode dot fit cool so now it's going to keep the aspect ratio but fit it within the v-stack so you see it fit it uh horizontally but we want to give it a specific frame here uh we'll do

frame width was 320 because we wanted to fill the whole uh thing but the height is 225 and actually I made a mistake you see it doesn't fill it because I put in the wrong number here for the frame I wanted to do 300. so now let's go up and change this to uh 300 like we had so it fills up

the the entire width there now that's the first major component of this card the second one is going to be as you see on the design that text information and that's going to be in a v-stack overall right so I'm going to add my v stack here and just for now I'm going to put in a text that just says title again what I'm building right now is kind of just My overall

structure of the card and then I go into each one of these components to to you know flesh it out so there's my v-stack and then the third component is my button again we'll uh just print tapped and then the label for the button which is where you design it again we built a couple buttons by now again for right now I'm just going to put text button again we're just building out

the structure now I don't want my button hugged up against you know all my my information right I want to add a spacer between my title and the button and remember what the spacer does it's going to push everything out so put a space spacer under my v-stack because really I want the button to be pushed all the way to the bottom there you go which also pushes everything up to the top

which fills in the card on my image nicely that's what I wanted there however my button is hugging the bottom like literally I don't want that so on our button let's add a padding bottom so we can do dot padding and then again we can specify like we could leave it like that but we just want to you know specify the bottom padding dot bottom and then we're going to give that uh 30.

so now you can see our button is pushed up from the bottom and you know we're going to design our button later but you can start to see the structure of the card you know taking shape so it looks like the image is good now let's start working on our our text in the middle right so this title we can actually change this to appetizer.name right and it should be like

test appetizer that's what our sample is now let's start changing the font so we want font of that title 2 and Dot font weight dot semi bold and again this is just the design I came up with you want to tweak this and make it your own go for it now the next piece of text we want to add is

our description right so we can do text appetizer dot description and then we're going to add a new modifier that we haven't used yet right because take a look at it it's not centered it's left aligned so to do that you can do dot multi-line text alignment again this is a new one instead of dot leading that's the default Dot Center right so now that centers it and then we want

this font to be body which again body is usually you know anytime you have like a paragraph or a description you typically want that to be body and then the last thing we want to add because it does feel cramped right look at it I'm going to get rid of that red outline right it's all the way to the

edges it's pushed up against the test appetizer so to fix that we can just add some default padding around it there you go so see it pushed it down a little bit into the middle got it away from the edges made it look a lot easier to read okay so pulling up the design again the next piece is our

nutrition information well you can see that's an H stack of V Stacks so let's build that so under the text here do H stack and then in here we're going to do our first v stack and then you'll see we'll just kind of replicate it three times so the first text we want is just a text and this is calories

now here we're going to change the font size to font dot caption and again I just played around with this to get a size and feel that I liked and I think if we did caption.font weight Dot bold that's how that's the look I liked and actually you know what let's let's do something a little quicker rather than spelling out font weight remember we can do this on text

just to point this out for educational purposes it really doesn't matter but I just want to point this out remember we can just dot bold on the text so slightly smaller but again educational purposes so now the next text we want is our actual number so text and we want this to be appetizer dot calories right and that's an INT so we need to do some string interpolation here

I'm doing this string interpolation Way backwards but whatever there we go so now you see 99 calories under it now we need to format this a little bit that foreground color I'll scroll up uh remember this dot secondary because we want it to be that gray I'm going to do dot font weight Dot semibold and then dot italic

so there you go you see we get that that look right the italics 99 now in this v-stack right the calories in the 99 is kind of cramped so I want this v-stock to have some spacing of uh five right so you see that made it uh breathe a little bit more so now what we're going to do is copy this v-stock two more times right because it's going to be the same format and we're going

to refactor this whole screen in another video we just want to get it working first so one v stack two v-stacks and now you can see it's not looking exactly like we want um but you can see the structure is there so let's go up to our H stack and if we want these to be spaced out a

little more like look at the red box like maybe I want that to be wider you know they're too close together so again we can add some spacing on our hdac and we're going to let's try 20.

let's try 40. now again just tweak it dial it in it's the nice part about these previews okay that's spaced out enough I feel like it looks it looks symmetrical with the rest of the text in our v-stack so we're going to go with 40. now the only thing we have to change is we don't want calories every time right we want uh carbs and then make sure there's appetizers dot carbs and then protein

and then appetizers dot protein so there you go now we're starting to get this layout uh looking good the last thing we need is to style our button so here in our button label instead of well we'll keep just text for now we're going to change that in a bit but I want to get it formatted first so let's change our font so we'll do font it's gonna be title three and font uh weight

dot semi bold and then our frame is going to be 260 by 50. remember this is kind of the my go-to button size I feel like it feels like those apple buttons um we do need to give it a DOT foreground color of dot white because we want our button title to be white well we just lost it so let's

give it a background color dot background color so we can see our text here uh color dot brand primary right remember we created the extension on the color so we could use it easily so there you go there's our button uh we are missing our Corner radius so dot Corner radius of 10. okay

so now looking at our preview let me click off so I can get rid of that red outline cool you can see our card of our description is coming into shape right we have everything we need looks good um we're missing two things right if you look at the design our button actually shows the price of the item so we want to incorporate that into our button and then we're missing

the overlay which in the upper right hand corner that has our x button that we use to dismiss the detail view so let's take care of that okay so back down to our button the title again we don't want it to be button we want a dollar sign string interpolation here to get our appetizer dot price but if you look at our button remember we have to use the specifier to say we only want two decimal

places we don't want all those decimal places unless you do for some reason specifier again the string is uh percent dot two F to give us the two decimal places cool so we have the price of our appetizer now we can add a dash and say add to order right so now the button says

9.99 add to order on the button so cool we've customized our button to show the price uh and it's Dynamic based on whatever appetizer we have okay so now let's talk about our overlay and this is this is new we haven't talked about this yet so on our Z stack right which has our frame you know Shadow Corner radius we're going to add an overlay so I'm going to start off simple

and then we're going to build up to our button just to explain this so if you dot overlay you can see it takes in and overlay content right so let's just for right now uh give it a text of we'll say test right and you can see uh or I put text let's say test right so you can see it's

right in the middle it overlays it it's kind of like a mini z stack right that's how it's treated it's an overlay on your v-stack so right now it's in the middle well we have an alignment uh a parameter and you can do if you hit dot you can see bottom uh bottom leading top top leading so let's do uh top trailing because we want it in the upper right hand corner so if I do that

now you can see our test got pushed up all the way to the upper right hand corner so again you can overlay text you can overlay basically any view so this is going to look ugly before we refactor this is also a good reason to refactor but I wanted to show you the two basic elements right so you have

your view here uh right now we just have our text for us it's going to be a button right it's going to be our circle with an X in it and then you have the alignment okay so just keep those two factors in mind so let's create our view in our view again is just going to be a button which

is the typical uh button layout here right you do the first uh closure here and remember the first part of the button is the action so for right now we'll just say print dismiss and then here at the end of the closure like I said this is where it gets it's confusing for right now um label and then write the the second you know Trail enclosure this is

multiple Trail enclosures is why you do that so again just the structure here right we have our overlay the item that used to be a text well now just the highlighted part is our button right remember the button structure uh that just replaced our text so the highlighted part is item one and then the second part is the alignment right I know this can look confusing the way

we have it right now but I wanted to highlight that so now just like the button up here right the label here we can style however we want right get our button to look what we want it to look like well our button that's the circle with the X on top uh just think about the way I just said that it's a circle with an x on top that's the way our button looks like so

that's a z stack right the circles on the bottom the x's on the top so Z stack and then we have the shape remember we think we did this with a rectangle before in the in the barcode Circle same thing but that's obviously not what we want it to look like so let's give it a frame

and we're going to do 30 by 30 because again it's kind of small in the upper right there you go you see how it pushed it into the upper right and the reason I did that is because our alignment is top trailing right so okay so it's all the way in the upper right we still got some work to do we don't

want it to be blue right so dot foreground color is dot white and we want it to be white because you know even in dark mode you know we want it to look the same and it has a nice little touch I like to do uh not just a solid white just a DOT opacity and we'll say dot six for like 60 opacity

oops I got to put a zero in front of that so 0.6 and again it's just subtle see-through right you can't really tell on the Asian flank steak image but some of the other images you'll be able to see very subtle you know Alpha there and then now we got to put the X on top and we're gonna do the

same thing we did in the Frameworks app where we use uh the SF symbol for an X and we're going to give it a frame to give it the bigger touch Target all that stuff so this is a little bit of review it's the same exact thing we did there uh really the only difference is there's a white circle go under it for styling purposes but anyway image this is going to be system name because we're

using it as SF symbol system name and this was x mark again same thing we did dot frame we're going to give this 44 by 44 and this is a little little trick I did right I didn't make the circle 44 by 44 because it looked ridiculous in my opinion it was too big too overpowering however you can

still make your image right you can see the red square around my image which will also equal My Touch Target on the button so that way I allow the user forgiveness on tapping the actual button uh you know but it's kind of like invisible and then actually on the image let's do dot image scale and then here's we can do like medium dot large or if we do dot large that's too big that I don't like

the way that looks keep an eye on like the upper right as I change this let's do dot medium that's okay I actually actually think I like the small better I just like the way that looks right okay cool and then uh the last thing we need to add is the foreground color because right now it's a blue

X that doesn't go with our our Motif uh so we want to do foreground color dot black not blue black all right there you go so that now our X is black as you can see in the upper right hand corner so The Styling and layout of our detail view is complete I'm curious if you did the challenge how different was mine um did you see anything that you disagree with what I did I'm happy

to discuss that in the comments um did you see anything I did that was like oh wow great idea um again I always like comparing and contrasting other people's implementations because like I said there's many different ways you know to put this together but the last thing I want to mention because we're gonna we're gonna keep working on this for two more videos is look this is

this is quite long and believe it or not you'll see a lot of Swift UI code like this that's not refactored out and I just think this is this is hard to read so in the next video we're going to connect the the detail view that way when you tap on a row in the list view we'll show this we're going to get all that connected and then in the video after that we're going to refactor

it and that goes back to the lesson of like get it working first then refactor right that's the thing I want to drill into your head as well so let's move on to getting all this working we left off last video getting our appetizer detail view UI built now let's connect it to our list view so if you go to appetizer list view let's talk about how we're going to do this

um okay our preview let's just get rid of the preview because we're just going to be looking at the loading screen the whole time so I'll buy some screen real estate uh so thinking about how we're going to do this right we want to tap the the list row right the appetizer list cell we want to basically add a way to tap if you're familiar with UI kit we're basically implementing the same thing

like did select item at index path uh however we don't have index pass we don't have table view delegates it's much simpler than that in Swift UI we do on ourselves right not on the list like on the actual cell itself because we want to know like which one we tapped we can do it uh modifier on tap gesture and then we get the code here and what we want to do here is one you know

display the detail view that we have but we also need to pass data right we need to pass whatever appetizer we tapped into that detail view okay so we're going to need a variable for the selected appetizer and we're going to need you know a state variable like is showing detail right to back to the whole reactive programming declarative right we need to flip is showing detail and that's what

determines if the detail view is showing so let's do this one at a time let's first get our detail view showing okay so here I'm going to create at State uh private bar is showing detail it's going to equal false by default and when we do the refactor in the next video we're going to move this into the view model again I like to get it working here first and then refactor okay so

on tap we want to flip that to true so is showing detail equals true okay so we're changing the data but like nothing's listening to that data yet well let's create that and very very similar to what we did with our loading view right like remember a couple videos back like if we're loading hey slap the loading view on top of the z-stack that we created well our detail view is also going to go

in the Z stack however it's it's above the list view like as you see in the design we have the list view in the background with the detail view on top but it's not above the loading view so it's in between them so again very similar concept uh to the Loading right if is showing detail then we'll show the detail view so appetizer detail view all the way at the bottom initialize

a new one we're gonna have to initialize that with an appetizer for now we're going to initialize it with the sample that we're using right the mock data run we're going to eventually switch that out but just to get this first part working let's try this uh mock data dot sample appetizer cool okay so now let's run the app and try this so again we put a tap gesture on the cell when the cell

is tapped we're flipping our issue in detail you know to true or false and because we're watching that is showing detail because it's a state variable we're going to redraw and then if it's showing detail is true then we're actually going to initialize the detail View and show it in theory run it see what we got here okay let's tap on let's just pick one right let's pick meatballs

okay well it didn't matter what we picked because we're not passing the data yet all we were testing was to make sure we we got our detail view showing up when we tapped the cell and we did okay so now the next thing we want to do actually while we're here because right now like I'm just tapping dismiss and nothing's happening so let's get that part working again before we start passing

the data so we're just going to get the structure of the UI working first if you remember it's the same thing as the framework uh detail view that we did before so we're going to need a binding to is showing detail in our appetizer detail view right because when we tap the X on our appetizer detail view we want to flip is showing detail to false so this redraws and then hides the appetizer detail

view okay so on the appetizer detail view another property we need at binding VAR is showing detail right and that is a bull okay if I do a command B uh xcode is going to yell at me because now I have to initialize my appetizer view with the binding so back to the appetizer list view do command B because I want xcode let me right here cool missing argument parameter right it's saying

hey you sit out of binding you're not giving it to me so is showing detail you want to pass a binding to is showing detail and again I know I'm repeating myself but really driving this home that is a binding to this state VAR here right so think of a binding as almost like a reference you know between views and then again I'm going to put the parameters uh down here for for ease of reading

okay so now now that my detail view has this Boolean I need to flip this Boolean accordingly and where I want to flip this Boolean is in my overlay down at the bottom that we created up the previews how many times I'm telling you you're going to be so annoyed with these previews um so again we wanted for the previews we can dot constant and then just give it you know a value

true and then for ease of reading cool okay so anyway back to our overlay button right remember the circle with the x button well here instead of just printing dismiss which you can see in the console as I was tapping it now we want to do is showing detail equals false and again that will change this binding which is a binding or if you want to think about

it as a reference to this is showing detail it'll flip that it'll redraw The View and then we will not be showing the appetizer detail view so test it out cool click on chicken dumplings there it is again we've got more work to do with the UI but hey it's showing up hit the X it dismisses great the basics are done tap on another one cool there

it is now okay before we pass data let's set up our background blur because again looking at the design right it's a nice blurry background on top you can see the shadow making it pop uh back to what we have like this doesn't this doesn't look great not to mention it doesn't look great but look I can scroll behind you don't want that and I can like even tap something else I mean

you can't it does pull up another detail view you can't see it but it messes up our UI like all you know all the time by like being able to scroll behind that okay so let's handle the blur and then we're also going to disable the list so you can't interact with the list while the detail screen is showing all right so let's do the blur first so on the navigation view right

that's what I want to do this on I don't want to blur out everything else just the list essentially um so under on up here I want to do dot blur pretty straightforward this was a lot more complicated uh in UI kit and then we want to give it a radius I want to give it a blur radius of 20. however not all the time right because if I run this you know

that's not what we want right we don't want it on all the time we only want to show the blur when is showing detail is true so we can use the turnarity operator here so is showing detail ternary operator when it's true B20 when we're not showing detail be zero so let's run this real quick so our blur should be gone because is showing detail is false cool blur is gone now

let's tap an item cool blur is there right that's the look we're going for now you can see I can still scroll in the background right that's that's not what we want bad behavior not what we want so now that the blur is handled uh let's disable the list using the same logic uh here that we only want to disable it when is showing detail is true so disabling a view is quite simple as

well and we want to disable our list so below the navigation Title Here which is our list modifiers type dot disabled right and now we need to pass in a Boolean well what Boolean do we want to pass in is showing detail so is showing detail and what this will do is you know if is showing detail is true just disabled will be true if is showing detail is false disabled will be false which

is the behavior we want run it and test it out again you want to be testing like step by step so you know like if you have a bug like what broke it uh okay now look now I can't scroll uh on the back so that is the behavior we are looking for uh the only thing we are missing here is actually

showing the correct uh data here so let's stop running this and let's talk about that um at the beginning of the video I said we're going to need two things right we're going to need the variable for issue in detail we've handled that now we're going to need how do we track the selected item right what appetizer was selected we need to you know track that somewhere because we need to pass

that into our our detail view right and we have that appetizer locally but only locally like on our list right we don't have access to it outside of that scope into our detail view so we need to create a variable that holds that and it needs to be State because again we want to hold hold State we don't want it to you know revert back to no value uh you know when our review gets destroyed

and recreated we want to hold State here so state private VAR you can say selected APPA Tizer and that is of type appetizer it's going to be an optional because uh right now you know there is no selected appetizer in the beginning so now what we can do in the tap gesture we can set the selected appetizer to whatever appetizer was tapped right we have access to that locally so

we can do selected appetizer equals appetizer so now that we have a value in our selected appetizer now we need to pass that selected appetizer into our appetizer detail View so just pass in selected appetizer it's an optional we'll force and wrap it for now now let's test this hit play and we're

going to see it half working okay and see if you can think about why it will be half working you may not know uh it's because the uh the image watch the image no matter what I type or tap so I tap meatballs cool I get the meatballs title the meatballs description all the stuff about the meatballs just not the image the reason being is because we never set that up remember we just used

our dummy image so let's close this close this go back to our appetizer detail View and instead of just using the image which we hard coded the Asian flank steak right well now we can do our appetizer remote image that we created a couple videos ago right and the URL string is going to be appetizer

Dot image URL and then again because we're already using resizable within the remote image we can delete that do a command B we should be good to go now the way we have this set up like you may be thinking oh man we got to download this again when we tap it but if you think about how we have

this uh set up on downloading the images remember we're putting them in the cache with the image URL as the identifier so what's going to happen I'll walk through this so let's make sure we have it working before I explain it so let's tap on chicken avocado spring roll cool there's our chicken avocado spring roll there's a long title uh description everything seems to be working

but what's going on here is we're not when I tap this item here right I'm not actually downloading the image again and that's because we put it in the cache back to our network manager right what happens here is it's going to go into download image but the first step of download image is to pull it from the cache if we have it and because we've already downloaded them the first time on

the list they're pretty much always going to be in the cache when we go to the the detail screen and if for some reason it's not okay we'll download it again but that should should never happen famous last words the developer that should never happen we're good we're safe so anyway that is our detail View you know connected up and running working again just the basics of it

um so cool looking good and then in the next video we're going to go back to our appetizer detail View and uh clean this up a little bit and then in our appetizer list view right we should uh we should have these on our view model not in our view but again I wanted to get it working and then refactor so let's do it we left off last time getting our detail view just connected

to our list view with the blurry background looking good uh what's not looking good is our appetizer detail view it's a what a mess so let's stop this and let's start refactoring um I'm going to start with the buttons just because I feel like we've done that before that's kind of review so let's refactor out this kind of main button again this is the price button

at the bottom uh this should be review I think we've done this twice now but here in the views folder let's create a new group called buttons and within buttons new file and we're going to make this a swift UI View we're going to call this AP button again AP short for appetizers uh hit create

cool and then in our appetizer detail view I can literally copy and then back to the AP button replace text with paste and instead of We're not gonna like pass in an appetizer which you may be tempted to do because not all buttons are going to need appetizers we just want to

pass in the string that is the text right so we're going to do let title and that is of type string so we can just get rid of all this and make this the title right so whatever title we pass in that's what it's going to be again keep all our formatting there cool good to go let's check out the canvas oh I'm gonna need a need a title that we didn't again

previews always get me maybe you're better about the previews than I am they always get me uh so we'll say test title and support the canvas just to make sure uh we got this cool yep there is our button so if you did want to play with the button maybe make a crazy gradient or Shadows or whatever you want to do this is your playground to like test that out okay so

back to the detail view uh here we already have our button highlighted let's do I'm gonna I'm gonna keep that text because I'm going to copy and paste it actually I'm going to copy it right now or command X whatever just get rid of all of it because this is going to be a AP button but an AP

button takes in a title and the title is a string that I just copy or cut and pasted right so that's the string we want to put for the AP button hit try again okay what did I mess up oh yeah that's right uh just a normal string doesn't have this specifier we need to go back to our AP button

and make this a localized uh string key and then now if we go back to the detail view do command B now we get that specifier okay so there we go we got our specifier now our preview still uh looking good uh and our AP button has been refactored so now the other button we want to refactor is our Circle X right because that adds a lot of like bloat to this overlay makes this overlay

like 12 lines of code so let's basically do the same thing we just did right we can uh I'm going to cut it actually so command X to cut that Z stack and in buttons new file new Swift UI View call this uh I can't remember if it was dismiss x button or X dismiss button I'm gonna go with X dismiss button again because this is a common type

button that you're probably going to use you know throughout your project and instead of the text we're going to copy and paste the Z stack there let's take a look at our preview yep there it is again you can't see the white circle because we're on a white background that's all good let's go back to our appetizer detail View and instead of having nothing here let's

call X dismiss button and there's nothing we got to pass in it's just generic okay let's run this to make sure our refactor is working make sure our X dismiss button still looks how we expect yes it does in the upper right and we tap it um we're good okay cool stop running that so again I always like to test along the way on the refactor because it's very common to break things you know when you

refactor it thinking got it all set up right okay so the next thing I want to take a look at right we refactored our buttons got that looking nice and neat the next thing I want to look at it's really kind of out of whack right like our image that's fine um the the top text of our v-stack uh

you know this is a font of Title II semi-bold this is very different right it's body multi-line tech center so you don't want to like refactor that into the same thing I mean you could refactor these out so this would just be like you know description text and then you pass in description I find that uh unless I'm going to reuse that like all over the app then yes of course refactor

it out um maybe you want to refactor it out for practice great even though we're not going to use it but I find when there's just like one or two modifiers I think it's simpler to keep it here because it's easier to change it's easier to like see what's going on it's in the case of like our button right like going back to the AP button like when you have what is that six modifiers

X dismiss button like it's a z stack like that type of stuff I refactor even if I do only use it once but back to the detail view like I said there's only there's only two I'm not really reusing it so I tend to keep these but if you want to refactor it I wouldn't I wouldn't argue against that however these V Stacks you know that are our nutrition right these are being reused so

I would refactor these okay so what are we going to need right we're going to need a title because it's different every time and then we're going to need a a value right the the 99 that we'll pass in so let's uh command C and again this is the case where I would keep this in the same file again unless you were using this nutrition stuff elsewhere in the app but I would keep this in the

same file just for ease of use so we'll call this struct uh nutrition info and that is of type view and I'm going to scroll up get out of my face and we got to conform to that right so VAR body some view again the typical Swift UI view now like I said it's going to take two properties right

so we need let title that's going to be a string and then let's uh we'll call it value and that's going to be a string as well in fact you know what I'm actually going to make this an INT just to be very clear what we want to pass in because we'll handle the string interpolation down here okay so

again let's let's paste the v stack that we copy and pasted okay so instead of calories I want title right so whatever we pass in and then here's we're doing that string interpolation uh so it's expecting an INT so we'll just pass in uh value there right so title and value and now let's go

up to our H stack instead of having three V Stacks here we can do nutrition info and you can see it's going to take in a title and a value and the title is going to be carbs and the value appetizer dot carbs and then I'm going to delete these V Stacks because we don't need them and really just copy

and paste our nutrition info two more times so one two cool hit resume on our preview to make sure everything is fine cool except you obviously we don't want carbs each time we want this to say actually I think I got those out of order I think it's supposed to say calories than carbs I think it was calories protein carbs either way the order doesn't matter do whatever you want uh

Galleries and then carbs carbs and then protein if I change the order uh oh well not a big deal but you can see how our H stack looks nice and the reason why I didn't like refactor out the whole hdac uh you know because you could have done that and then just said like nutrition info hdac or

something like that I I think with when you look at the screen and you see this three of these like to me looking at this image that's in the red square and then seeing this to me I don't know if maybe I'm just experienced with code maybe you don't see that but that's automatically related right it's obviously three of the same items I can see that's three of the same when I say items like

um like UI elements I should say three of the same UI elements and I can see that's three of them so to me I make the connection in The Code by having this spelled out with three items so again I'm just giving you the insights on like how and why I choose my style and to format my code like I do because again I'm always aiming for ease of understanding right I'm not trying

to be super clever I'm not trying to be like hey look look I did this in four lines of code it's like no that's confusing what is the easiest to understand for a new developer coming in that's what I'm always thinking about when I try to style this so now that we have that refactored I would say our screen is is looking uh a lot better right let's let's run through it again we have our

overall v stack which is the card right and this is all the formatting on the card the Shadow the corner radius the background color cool and then we have our v-stack which is the text information here and then within that v-stack we have our H stack with the three nutrition info views and back to the refactoring discussion like I said if you wanted to make this just like you know

title view you know bot or description view you know that could clean it up again we've discussed that I don't want to go down that path again our button nice and clean AP button and then our overlay nice and clean X dismiss button so I would say our nutrition detail view uh refactored pretty well now let's go back to our appetizer list view the last thing we're going to do in

this video get rid of the preview here because it's useless now the small adjustments we we want to do here is like I said the view should be as dumb as possible so we want to move our issuing detail and selected appetizer into our view model so I'm gonna command X to cut that and get rid of that spacing there open up our view model and then here below our variables here create two more and

then instead of at State and private again these are published because we want to let whoever's listening know when these values change okay and then as you may have guessed now that we no longer have issuing detail an appetizer in our list view uh we should get some errors here saying hey yeah what is this show in detail so again it's a view model Dot and then when I refactor and I know I'm

going to type viewmodel dot everywhere I'll copy that and then you know just kind of paste it in front of all the stuff that's applicable which again is our selected appetizer and our is showing detail so that's all I did if you thought that was fast all I'm doing is pasting the viewmodel dot in front of everything and some people you know maybe view models long this is subjective

but some people will do VM for viewmodel to keep it short some people just say model subjective do you uh but anyway let's run this and make sure we're looking good after the refactor cool chicken avocado spring roll looking good dismiss that everything seems to be working these stuff shells are my favorite I just want to keep looking at them this app has made me hungry

like all the time working on it I see add order just you know the tap that shows up so we need to eventually have this actually add it to an order to show up you know in our order screen and we're going to create our account screen but all that is to come let's keep it moving over the next couple videos we're going to get this account screen that you see here up and

running and if you look at the screen like it's a pretty common looking screen right looks like a typical settings screen account screen these are like all over the place in iOS apps and this type of screen for building the UI for it like this is where Swift UI really shines because we have an element called form that basically does a lot of this stuff for us and it's great so that's what

we're going to build over the next couple videos let's get going okay so here our next code make sure you click on your account view right remember we set up this just basic skeleton view which is like our Network view shows account let's actually pull up the canvas to see this and as always make it small hit resume zoom out a little bit to 75 so it's not ridiculously huge we are on the iPhone 12

Pro cool okay so like I was saying just the basic view we set up before but let's wrap this text in a form and then watch the preview you can see what we get just by wrapping it in this form element here let me actually put the text inside the the form command X and then then put our navigation

title on the form element cool now if we look you can see the beginnings of our form right it's just a text this is account it's not a text field or anything like that but you can start to see it taking shape and we get that format automatically just by being inside this form and now we're going to format our first section because again if you look at the design you see how our form is broken

up into sections with Section titles well that's also relatively simple as well so inside our form section we initialize that and you see it can take a header and then content so the content is is what's going to be inside which is going to be our text our header is going to be a text that says personal info right this is going to be our first name last name email and then content just

like we've done with all these before is now our view Builder here with the text put the text inside the section so now you can see what it looks like uh do a command B make sure all of our errors are gone cool resume the preview should be good but now you can see again our form starting to take shape we have the purse no info label that's our section header and then we

have one element in the section which is just our text of account but again it's taking shape but we don't want just a text in here we want a text field and this is the first time we've been using text Fields so uh new stuff here so text field you initialize that uh just like a lot of stuff

there's a different things you can initialize it with but the main thing I want to point out is The Binding to the text so the first part of this I'll just hit return here the first part of this title key is the the title like what you want your text field to say so this is going to be first name and

then the text we need a binding to a variable to hold the value that's in the text field right like if I were to type Sean in the text field I need something to hold you know that value of Sean or whatever I type in there so here we need a binding to that so we can create a state variable up here

so at State private VAR first name and that is of type string actually we won't Typecast it we'll go ahead and just initialize it with an empty string use the type inference there so we know first name is a string so now when I put the binding to this first name variable now whatever I type in the text field will be the value of my first name right they're bound together so again for the

binding is dollar sign first name we get that so hit try again to uh rebuild our preview here now this this account text view on the preview will turn into a text field if my preview ever gets going try again tiny man these previews so there you go now you see the uh the text field with the

first name right you see that's the the title we gave it and then the value as we type in like if I hit play and I start typing uh s-e-a-n right so now the first name variable is going to be whatever I type in there right we've created the text field and bound it to a variable that's how text Fields work we're going to do this a couple more times but that's the overview so pulling up

the design we're going to need a last name and an email so let's build those two text Fields as well it's going to be the same thing as the you know the first name last name so we're going to copy do paste paste so instead of first name we want last name and instead of first name we want just

email right and now we're bound to first name that's not what we want right we got to create State variables for last name and email so again I'm just going to copy the first name paste paste and you see invalid redeclaration yep I know I know I gotta make these different so last name and then email and then we'll hit resume on the preview and then again now you can see the form

coming together first name last name email and these are all text Fields now just like text fields and UI kit you can customize them so for our first name and last name you know we want we want Auto capitalization we want maybe autocorrect or maybe if you don't turn that off but in the email we definitely want to turn that kind of stuff off so I'm going to show you how to do

that on the email text field and you can do this with modifiers so I can do that keyboard type and see if I hit dot there's a whole bunch of keyboard types right like if you're entering a phone number you can show that well for email there's a special email address keyboard type so let's make sure we do that so again pulling up the proper keyboard and then we can do Auto capitalization uh equals

none again you see sentences words all characters for an email we want none we don't want any auto capitalization same thing with autocorrect right don't you hate when your uh email autocorrects right so we're going to disable auto correction okay so we have the first part of our form you know coming together uh pulling up the design okay we need a date of birth and then a save

changes button so before we've been dealing with text Fields now we need a date picker and a button in our form well it's just as we do the text field it's the same kind of flow here so I'll scroll up a little bit we can do date uh picker and get the initializer here and I want to do title key selection and then displayed components so this display components is the important part because

you know a date picker can be flexible you can be picking a time you can be picking a time and a date you can be picking just the date well in the case of our birthday we just want the date right like I don't need to know what time you were born I just need to know the date so we'll use that one

so the title key again is what we wanted to say so we want this to be birthday and then the selection is just like we had to do with uh our text field we have to keep this value in a variable so again uh at State private VAR birth date is going to equal uh just initialize a new date for for the

start so now let's set up that binding here so dollar sign birth date so again now whatever date we select from our date picker we're going to store it in this state variable of birth date and then like I said displayed components so I'm going to hit Dot and you can see date hour and minute Etc we're just going to dot date because again we just want to know the day so hit try again

on the preview and you can see now we have the birthday uh that says today's date November 16th 2020 and if I actually run this now when I tap on that November 16 2020 you can see we get the calendar and then we can go back and select our birth date now you might be noticing like a user

experience issue right like man if I was born in 1981 I know I'm old I'd have to go all the way back to like 81 right so we're going to fix that in the optimization section where we actually come up with some logic as to like what type of date we want to show and dive into that but but

again I don't want to I don't want to derail this video with that quite yet we'll come back to that let's get our form built so now that we have our birth date uh we just need a button right we need that save changes button so if we change any of this or create this we can save it okay stop that

from running now uh we're just going to put in a normal button that we've used a bunch of times in the course already so we'll do button again the first closure is whatever you want the button to do for right now we're just going to do print uh save and then the label is what we want the button to look like again in the multiple Trail enclosures the second closure here uh we just

want a text right we're not going to get we're not going to get fancy uh the text uh you can't get too fancy in a form anyway but you know we're gonna keep it simple uh so save changes right and now you can see our buttons show up in our form uh on the right and then when we tap it for now

it'll print save changes we'll do we'll do more with that in a future video again this one's all about getting the uh the UI set up and speaking of that our first section uh right with the the email first name last name email date of birth button right the first section is uh is all set up nice and neat the next section as you can see on the design is where we start introducing our

toggles so let's do that so as you can see I have this section highlighted I'm not going to copy and paste because I'd have to delete a lot but I can just create a second section so section again we initialize it with a header and then content so again the header is a text and we're going to call this requests right the we don't know extra napkins extra refill

I just thought of some cheesy requests that you might want at a restaurant to demonstrate this um it's not easy coming up with like a sample app that you know properly demonstrates all the stuff you want to teach and makes sense uh that's that's tough to do so anyway uh like I said we want this section here to have the header of requests there you go you see my little

request title there's nothing in there yet but we want these toggles well that is just a toggle and we initialize the toggle you know the same way we've been initializing all this other stuff right we have to give it a title key and then it is on so the title key is again what you want the the

title of the uh toggle to be so for for our first one that's going to be extra napkins and then is on again same concept right we need to bind this to uh you know something's got to hold the the Boolean here so we'll do at State private VAR uh extra napkins and that is going to equal false to

start and I like to give these default values because if I if I just left it you know say hey this is up type bull then when I initialize my account view like I have to initialize these with like initial values anyway so you might as well just kind of like do that here okay so I'm just going to copy and paste this because we're going to need this again instead of extra napkins

uh it's going to be frequent refills this is our other option in the toggle that we can do I'm just kind of getting ahead of myself here so anyway the toggle on extra napkins is you guessed it dollar sign extra napkins and then let's hit try again on the preview get this going so we can see this cool there you can see our extra napkins toggle and let's go ahead and copy and paste this because

we're going to basically need another toggle for our frequent refills so again instead of extra napkins free sequent refills and then is on is not going to be dollar sign extra napkins it's going to be a binding to our frequent refills Boolean that we just created up here so now let me run this on my preview and you're going to see something that we want to change here

so I'm going to hit play extra napkins cool and I can toggle these but it's that default green toggle which really clashes with our uh you know brand primary right pulling up the design we got that dark green that you see so we need to add a modifier onto our toggle to give it that dark green color so if I stop running this I don't know why I keep stopping that I can run that I'm so

used to being like a simulator we got to stop and start it you can keep that running um anyway so on the toggle we can do toggle style that you see here and that toggle style will take in a switch uh toggle style and then if I initialize that you can see it takes in a tint which is a color we have dot brand primary right remember we created that extension on color to give

us our brand primary color cool now let's run it again on the preview let's see extra napkins is that dark one but frequent refills is not right you can see the difference there so what you could do and I'm gonna this is not what you should do but you could do copy paste look and then now when I flip these cool now they're both uh dark well if you remember all

the way back to when we talked about modifiers there are certain things that are environment modifiers so like if I have a bunch of toggles I don't have to have this like on each one right my environment for these toggles is this section so I can put this toggle Style on the section and what that will do for me is every toggle in that section will get that toggle style right so

I don't have to stylize each one individually just put that on the section and now again toggles are still dark green so now let's run this in the simulator to make sure everything is working good you know outside the preview because the previews can be weird sometimes again I always like to confirm on the simulator okay so here we are we have our typical table view let's tap on

account cool we have our account screen and you can see we got the dark green on our date and our save changing changes that's because it's part of our tab bar tint color and that's why it doesn't show up here on our preview because that preview is outside the context of our tab bar because it's like solo the preview well now that we're you know within the context of our tab bar we get

those tints however we had to change our toggles manually like we did just there so there's our account screen the UI looking good you know we have our our text Fields here you know Sean oh we messed this up see we forgot something but that that also demonstrates the the power of binding right so accidental lesson in here you can see my code on the left here right all my text fields are

bound to first name we forgot to change that uh my mistake but I think it illustrates you know if you if you weren't sure what binding does I think now you can kind of see it how you know no matter what I put in the text field it's bound to this variable so that's going to be the value right

for all my text Fields okay so stop this let's fix our mistake here so we're not bound to first name we are bound to last name and we are bound to uh dollar sign email okay let's uh run that again to make sure that is working again oftentimes mistakes lead to good learning lessons here so

okay so account here we have Sean Alan cool that is that is working we can tap on that nice I even misspelled my name cool anyway uh so that is the UI right again the the main takeaways here are just this thing called form and the nice thing about form and Swift UI is forms look different

on the Apple watch on the phone on a Mac but if you wrap it in form you're going to get like the native looking form for whatever platform you're on so a form is like really powerful and then again you if you want the section headers you just create the section and then put your items uh you know within it and again the text field the date picker the button because they're within form they

automatically take the The Styling that a form expects right when you put a text field you know off by itself not within a form like on a normal view it's going to look different same thing with the date picker and the button and all that stuff so it's nice that things inside a form will will adopt the proper styling okay that wraps it up for just the basic UI in the next video we're going

to refactor this into the view model add some basic text validation you know because we want to be careful what the user is like submitting so they can't just submit like all kinds of like gibberish and cause all kinds of network errors so that's we're going to handle in the next video let's keep it moving last video we created our form and got the UI structure for our account

screen done in this video we're going to refactor a bit into the view model and then also Implement some text validation and a little bit of error handling okay so the first thing we want to do is in our account view folder because again the view model should go in the same screen here do command n for a new file Swift UI nope just Swift file not Swift UI view this is our view model so

account view model cool hit create and again I you know my personal preference I like to have the V model on top of the view and okay cool import Swift UI hopefully some of this is starting to be reviewed right and maybe you can even try to do this yourself before I do it I know I didn't

issue an official challenge uh but you know if you want to try it give it a try final uh class account view model and that is going to conform to observable object and then now before we go any further let's go into our account View and actually create that view model and again we're going to initialize a new one so when we initialize a new one which one do we use

at State object we actually haven't even used observed object and again it really depends on how your data is structured if you're passing data Etc but anyway State object uh VAR view model equals account view model initialize a new one okay while we're here what we're going to refactor

is all this stuff and some other stuff but to start all this stuff here right so I'm going to command x copy that go back to our view model we're going to paste it here and then a little quick editing trick if you hold option and drag here you can like edit these all at once so these are not as state private bars anymore remember they're going to be published because when these

change we want to publish it our account view is going to be listening to those changes right said that a bunch of times hopefully you get it by now at uh published and VAR there we go and now uh as usual when we go to our account view we're gonna get all kinds of Errors because we no longer have

first name we no longer have last name right well just like we've done before we're going to view model Dot and then again just like I've done before I'm going to copy the viewmodel dot paste it in right in front of the dollar sign everywhere I need it okay so I basically just changed all the variable names from just the normal variable names to you know viewmodel dot you know whatever we we

needed I did a command B hit resume no errors we are good to go again I just like to test along the way this should be working but pulling up the simulator hitting account you know cool cool I can type something all right cool again just want to make sure you don't break anything when you're doing these big refactors okay so that first part of the refactor is out right in the

view model we got all the properties here now we want to start validating the text because again like we we want to let them know if they entered a wrong email like if the email didn't have an at sign or didn't have.com at the end right we want to let them know if it's valid uh or we want to

like hey if they missed a field we want to pop up an error saying incomplete form you know please fill out everything so this is just basic uh text validation text validation get pretty tricky if you have a very extensive form but this is just kind of a basic uh you know couple examples to get you started on that and for that we're going to create a computed property called is valid form

so I can do VAR is valid form and that is of type Boolean and the you know the computation that has to happen is here's where we check uh to see if it's valid or not and the first check we want to do is to make sure all the forms have some value in it right make sure it's not an empty form so we

can do guard not first name dot is empty so we're checking for an empty string right but we want to make sure like it's not empty right so basically we're going to do that for our text field so and and not uh last name dot is empty again same thing for the email and in dot email that is empty

cool so if uh well we can put this all in one line because we're just going to return false right so if any of these are empty we're returning false basically so is valid form it's not valid it is false because we have an empty field and again I just put that all one one line for for neatness oh I forgot my else yep there you go and then xcode's telling me I'm missing my overall return

so how this how this works is uh return true basically we're going to do these checks and if the checks fail we're going to return false if all the checks pass we're going to return true for is valid form that's the run down here so our first check is to make sure we have values in all the fields to make sure it's not like an empty form cool uh actually you know what

I just realized I can't put these all in one line because I got ahead of myself we are going to be you know showing uh an error item or an alert item so we'll make room for that uh for later so the next check we want to do is to make sure the email is valid and this is very common like

anytime you have like a login screen or anything like that you're probably going to want this check so this is a well I'm getting ahead of myself let's type this out first uh guard email dot is valid well what is that is valid we don't have that yet I know we'll we'll get there else return false right and we're going to pop an error message up there so we'll leave room for that okay

so let's talk about this is valid uh this is going to be an extension on a string that uses a regular expression to check to make sure it fits a proper format so as you'll see this is kind of complex and well beyond the scope of Swift UI fundamentals talking about regular Expressions but I'm going to include this extension as a file that you can download it's real short but go ahead

and download it from the below the video and then copy and paste into into your own project here but in our utilities right in our extensions folder do a command n for a new file new Swift file this is going to be a string extension so string plus EXT for that's the typical format for our extensions and then I'm going to paste this in as well I'll explain it don't worry but

um this is something that I carry with me from Project to project because again you pretty much always need to make sure the email is valid and this is why like I'm not going to explain this because I'm not gonna lie I don't know how to write these regular Expressions it's you can Google like regular expressions for password validation and it's some combination

of this gibberish right don't get me wrong it's valid people know how to use this stuff I never took the time to learn how to write this code off the top of my head I don't suggest you do either unless regular expressions are a huge part of like your job or your project but typical things you're going to use these for are you know to validate an

email again the password validation you know how passwords have like hey one capitalized letter one special character must be eight long like you can Implement all those requirements via a regular expression like this and again it'll be another Gobbledy goop of characters um but you know kind of what this does here is you can see I have a certain range of characters

where I can use capital letter A through Z one through nine and lowercase letters a through z basically alphanumeric here's some special characters I can use in my email write dashes plus um but you see this Plus at sign this means an at needs to be in my email right like my email can't just be Sean Allen right this is basically going to make sure I have an at sign in my email

and then before the dot in the.com like I can have you know this would be like the Gmail portion of the gmail.com the Yahoo of the yahoo.com um same thing you know alphanumeric capital A to Z lowercase A to Z zero through nine and then these characters um and then to make sure it has

a DOT and then it makes sure again A to Z A to Z uh and then here's the thing after the dot like the.com uh portion uh it must be at least two characters so an example of this would be like dot Co dot u s right two characters but it can be Max of 64. so that way you can't just have like

dot Z like because that's not a valid like domain name so that is like what the regular expression is doing uh now again these can get crazy complex I don't suggest you go out and learn them that's why I recommended just copying and pasting this in here all this is doing is checking to make sure it follows that specific format that I just went over okay so back to our account view model

now if I do a command b or is valid should be working if not I probably named it differently yes is valid email yes let's uh be very specific there so back to our account view model is valid email because really this this check can go on any string so if I just said is valid that's confusing right so we want to make sure you're checking for an invalid email so naming matters okay so now we

have the the logic for our checks in place uh the only thing missing is what we do when false happens well what we're going to do is show an alert and this is challenge time right here you have the project as it is we're going to implement something we've implemented twice already before and that is our alert item and then the updated alert context right so see if you can you know

use what we've done before add your alert item to the view model add your alert to The View and then update your alert contacts right if you haven't done my challenges yet this should be a relatively easy one we've done this three times it's the exact same thing so give it a shot I encourage that three two one all right we're gonna do it so like I mentioned we need to have that alert

item that we've had a couple times before now so at published VAR alert item it is of type alert item it is optional and here before I can like you know create these right I want to do alert item equals alert context dot well I don't have my alert set up so let's go to alert

context that is in our alerts folder in the alert okay so alert context we have these alerts I'm going to copy and paste because again we're going to use the same structure twice except here before we like uh customize these here's what I do because like I mentioned when we first built this this can get out of hand so there's many ways you can like organize it you

can create separate files in an extension on alert context to like group them that way typically what I do is I use just you know slash mark and then I will say you know Network uh alerts and then I'll copy this and then down here I'll give some visual spacing like

one extra vertical space and then this will be you know account alerts right so I separate them like that or again you could parse them out into their own separate files on extensions that's cool too but anyway this one is not going to be enabled complete it's going to be in valid form and then we'll tab this over to where it needs to be and then it's not going to be server

error again invalid form and then it will say please ensure all fields in the form have been filled out cool and then this one is not going to be unable to complete it is going to be invalid

email and then title same thing invalid email and then similarly please ensure your email is correct and you can write whatever you want in there but that's the message that's going to show up in our alert so if you do command B to make sure that's all good go back to our view model

now our alert alert context for our empty field should invalid form Okay cool so that's the alert we're going to show up if any of these are empty what don't you like command B okay xcode so now here we want to make our alert item alert uh item dot equals alert

context and that alert context of the email is invalid is dot invalid email so those are our nice clean alerts that we're going to pop up in those cases if these checks you know pass then we're just returning true which means our form is valid so now that we have this alert item being set properly again we're only doing one side of the communication pattern right now right we're we're

broadcasting we've set up our broadcast perfectly it's going to broadcast the right stuff nobody's listening to this alert right we have our account view set up to listen to The View model cool but we're not utilizing the alert anywhere here and again this is review we've done this before so on our navigation View scroll up a bit do dot alert and then again not just is presented because

that's where you got to pass in a bull we want the item because we're passing the item again this is review we want the binding to dot viewmodel dot alert item and then the content uh get rid of that open the closure alert item in and then here's where we create our alert and then initialize it

with a title message dismiss button the title is alert item dot title what are we missing I misspelled it I forgot the T up there cool and then alert uh item Dot message and then the dismiss button alert item dot again we've done this like three times by now hopefully you got it hopefully you did the challenge hopefully you got the challenge uh do a command B there hit resume

just to make sure our preview is working cool now we're about 90 of the way there we're missing the final piece of the puzzle and that is like what triggers all this so back to the view model right we've set up the variable but we're not like calling this variable or using it anywhere so here in the account view when do we want to do this we want to do this on uh when save changes gets

tapped so we got to create a function in our view model to do something when we tap save changes so in the view model below is valid form let's create a function here so func save changes and the first thing we want to do is check is valid form

right so guard is valid form else re return and we're just returning we're not showing an error here because our error handling is handled in this is valid form right so is valid form we'll check that so basically if is valid form is false we're just going to return out of save changes we're going to show the error properly if is valid form is true we're going to continue on

in this function for now we're just going to print changes have been saved successfully we're going to deal with this in a later video but for now that's what we're going to do to prove that this is working so let's test this and then I'll run through the logic again real quick as a review so back to our account view I didn't have to do that I guess let's just run it in the simulator okay

let's click on account now the first thing we want to test is empty form right so hit save changes I do this all the time this is I do this all the time all right hit stop you got to call the function if you want your function to run you got to call the function so instead of just

printing save we got to call it view model dot uh save changes okay that I do it all the time hit play and do this again okay now back to the account uh save changes there you go invalid form please ensure all fields of the form have been filled out okay cool I'll listen to you so click

in first name type Sean and by the way if you can do command K to hide and show your keyboard if you want to like see the UI um so Sean okay last name Alan cool that's all filled in email uh right that's not a valid email so hit save changes there you go invalid email please ensure your email is correct we can test our validation even further so we can do Sean

allen.dev at gmail right we have the at symbol but we don't have like the.com uh save changes nope invalid email okay let's try dot C right because dot C is not a valid email either save changes invalid email okay so.com save changes uh it printed should have printed uh yes changes have

been saved successfully as you see down there so our uh UI is done we've refactored it to the view model we've kind of handled uh text validation we've error handled a form because error handling on forms is important because as I just showed users can typically mess up a form so you want to be very good about your error handling in that case we just did some basic text validation there

um but yeah let's move on in the last video we did some text validation and got our view model on our account screen all set up in this video we're going to start talking about persisting data using the new property wrapper in iOS 14 app storage now basically what app storage is is its Swift ui's way of interacting with user defaults if you're familiar with UI kit you've

built apps before you're probably familiar with that concept if you're not a quick overview of what user defaults is is it's local storage on the device that will persist in between launches of the app now it is not a replacement for like a database right you don't want to store heavy things in there like images or a ton of data that is not what it's meant for a typical

use case would be like preferences or settings you know back when apps had to handle dark mode themselves you know you could have the preference you know prefers dark mode true or false and you would store that Boolean and user default or maybe you allow your user to select an accent color for your app right they can customize it you can store that color selection in user defaults so so what

app storage is is it Swift ui's way of monitoring user defaults so by using the app storage property wrapper you can kind of watch that item in user defaults and when that changes it's like a state variable you know the app storage will will see that change and then trigger a UI update to you know update the data accordingly where you're using that item now if you didn't quite follow all

that that was the overview explanation of course we're going to build it I'm going to be explaining it as I go so hopefully it'll make more sense then what we're going to build is a user object and store that custom object into app storage you know user defaults huge huge disclaimer right in a real app like you don't want to store your user in user defaults right because if the user

deletes their app user defaults gets deleted so they delete their user that's not what you want this of course would be stored on a server in a database this app is educational purposes it's it's actually pretty tough to come up with an app that's like realistic and covers all the topics you want to cover so I had to take some creative Liberty here so again huge disclaimer you're not

going to want to store your user in your defaults but it's the example I came up with to show how to do it because at the end of the day these apps this course like you have access to it forever this is a reference for you to come back to so when you're building your project you're like oh I

need to store a custom object in my user defaults how do I do that oh that's right we did it in the advertisers app let me go back and look right it doesn't matter what we stored there you can just come back see how we did it and then use that information accordingly disclaimer out of the way let's start building so the first thing we're going to build is that user object so here in our

model let's uh create a new file and it's going to be a swift file and we will just call it user hit create so struct user and here's the thing it's got to conform to codable and let me tell you why so when you're storing a custom object in user defaults or app storage now if I use user defaults and app storage interchangeably it's because they're kind of the same thing again app storage

is just Swift ui's way of doing it but anyway when you're storing a custom object into user default you have to convert it to data first right so when you're storing just like an INT a string you know a foundational type you don't have to convert that to anything user defaults can can handle that but user defaults doesn't know what my custom user is so I got to break that down into Data first

and then store the data and user defaults so the flow goes like this when we're storing into user defaults we need to go from user to data down into user defaults however when we're retrieving from user defaults right because we want to retrieve this data to populate our user on the next app launch we go we pull it from user defaults but it's data then we gotta convert that data into

our user object so that's where codable comes in because we're encoding and decoding data right we're going both ways if you remember last time we just used decodable because we were only going one way we were just decoding in this case we're going both ways so we're using codable now what properties does our user have well let's go to our account view model and it's basically all this

stuff we are replacing all this so I'm actually going to hold option I just want the VAR I don't need all the publish stuff command C to copy back to our user in here we do a command V to paste oh boy not what we wanted all right we'll make this work here I guess when you copy with the multiple

cursors it uh it doesn't like that so anyway neat little tip here highlight your whole thing Ctrl I will do the automatic indention here and then if you know me you know I got to tab these babies over you don't have to do this this is just my personal style I think it looks neater but again I don't think I've said that too much in this course last course I said that a ton so yeah

our user is going to have a first name last name email birth date extra napkins frequent refills right basically all the stuff that was on our form so now with this on our user we can actually go back to our account view model and replace all this stuff with just a user object and make that user object published so we'll delete all the well up until published and then we'll go VAR

user and then that is going to equal and we want to initialize an empty one and when we initialize this empty one if we go back to our user object right we have default values for our properties that's why I just copied and pasted that over so when I initialize a user and don't give it any values it's going to give it blank blank blank today's date false false because that's how we

want our our empty user to be when we first open up our account screen and see the empty Fields so back to account view model that's why I can initialize of empty user but I also get the memberwise initializer that has all this stuff you know for if when I need to create a real user but for now we're just creating the empty one okay so we're going to get a ton of Errors because

we deleted all those properties right so right now I need to do user dot in front of all this stuff and in fact so much I'm going to copy that user dot just like I did the viewmodel dot in pay paste it everywhere I need it right so instead of just first name it's user.firstname user.lastname

user.email instead of just email user.email and then as you can imagine on our account view we're going to have all this stuff as well so again viewmodel Dot and after the dot user.firstname

after the dot user.lastname user.email so all I'm doing is just adding viewmodel.user dot whatever we need here because again everything is attached to our user object now and not separate properties okay so let's run this on the simulator just to make sure nothing broke everything should still be fine okay and if I hit account here you know first name Sean last name yep yep yep yep

save changes we're gonna get an error because invalid email cool okay everything still seems to be connected and working good to go again that was expected we just refactored a little bit to get set up for this okay so back to our view model uh we need to one save our user to user defaults uh using App storage and then also retrieve it so we're gonna have two functions for that well

we kind of already have one function to save changes I'm actually going to move this up top I like it up here and then we'll need another function Funk retrieve user so this is what it'll get called when we want to retrieve it and save it so let's set up our app storage first and that is the app storage property wrapper so it would be at app storage and then here you have to give it

a key and that's a string and our key is going to be user again if you're familiar with user defaults you had to give it a key because there's a key value pair in user defaults so you would get like object at Key and it would have to match this identifier so our identifier is going to be user I'm going to do private VAR we're going to call this user data because remember it's going to

be data it's not like our actual user it's going to be of type data but it's going to be optional because again remember like if we've never saved a user we don't have a user there okay so let's clean up this top part a little bit let's work on Save changes first right okay we no longer want to print anything we want to encode our user into data and save it into user defaults so just like

we did in our Network call I'm going to go back for a review here remember on our Network call here where we're downloading the appetizers and we have to decode our Json response so we're going to do code that is very very similar to this where we created the coder and we decode it into an object just for review there what we're going to do so back to the account view model we're going

to do a do try catch so do and what we want to do is encode our user into data right because this is where we're saving it we're converting our user into data saving that data into user defaults so let data equals try this is the try of the do try catch block and we want to do Json

encoder right not decoder we're encoding it to data create a new one dot encode value is user so we're encoding our user that's up here published right and that user is constantly being updated as we type stuff and then in order to save this user user defaults we need to set

our user data variable up here that is app storage equal to that so we do user data equals data and then it's I'm getting an error because I haven't written out my catch block yet so catch so now we want to handle the error like just in case this encoding went wrong because remember it goes into this catch block if this encoding fails and usually this encoding will fail if like you messed

up your model and like you had a typo in here or it doesn't quite match that's the common reason why this will fail but still we want to create an alert here so back to our account view model well we already have an alert item right we've already set that up for our is valid form so now we just need to pass in a different alert context for the specific cases so back to our

alert let's create uh another alert context here again copy and paste to get to structure so this is going to be called uh user save success and here in the title we'll say profile saved just that and we'll say your profile information was

successfully saved done okay back to our account view model do a command B to make sure we get some autocomplete here so now in this uh well that was a success case I meant to do the error case but hey I got ahead of myself uh we need to do that here right because we want to show a pop-up when it was saved successfully we don't want them to just hit the save button and then like

nothing happened right we want to notify them that hey this was saved successfully so we can do alert uh item equals alert context Dot user save success okay so now we need the error one

back to our alert we got to create that again copy paste and we'll call this one invalid user data and then what we'll tell the user is call it profile error

say there was an error saving slot or retrieving your profile because we're going to use this for for both when we try to retrieve it and there's a failure and when we try to save it and there's a failure so again that is invalid user data and again these error messages like I said I'm not an error message Pro you know you want these to be really really good to let your user know

what's going on back to the account viewmodel so now in the catch block we'll do we'll set our alert item and if you remember whenever our alert item changes value it's going to trigger the UI update and show it alert context dot invalid user data okay clean this up here so now let's walk through this when we tap save changes on our account screen first we're going

to check to make sure the form is valid right we don't want to save anything that's invalid then we're going to encode the user which is this user here which if you remember anytime we're typing in the field this user is getting updated because it is published it's attached to our text fields and all that stuff so whenever we hit save changes whatever user we have we're

going to encode that into Data we're going to set our user data equal to that data and our user data is our user defaults essentially again that's what the app storage property wrapper does so it's going to save that data at the key user in user defaults and then if that goes through successfully we're going to pop up an alert that says users say successfully good to go if for some

reason the encoding fails we're going to pop up the invalid user data okay so let's run this let's go to account first name Sean okay let's hit save changes okay invalid form they're not filled out that is still working always want to test that okay Allen email Sean on allen.dev gmail.com birthday we'll just leave that it is again we're going to optimize this birthday thing later

um cool April tax day or day before tax day cool I want extra napkins I want frequent refills okay so remember that April 14th 2020 I flip these on see my name and my email hit save changes profile saved your profile information was successfully saved right it went into our do block success hit ok now what we're not doing watch when I stop this and I run it again it's going to be blank

because if I go to account again like we're never retrieving from user defaults all we did was save to it so the next thing we got to do is retrieve it okay back to our code okay so we're going to do that in retrieve user and again I like uh two spaces in between my functions here okay so

retrieve user the first thing we want to do if you notice our user data is nil right when we haven't saved anything yet right the user's first launch or they haven't created a profile it's going to be nil so we want to make sure we actually have data there before we try to decode it because what's going to happen if we try to decode it and it's nil it's going to go into our decoding catch

block let me let me actually write out the code that'll make more sense when I say that but we need to guard let user data equal user data else and we're just going to return if this is the case because this is the case on like again a fresh launch and how we're handling the fresh launch is we have this default blank user that we're initializing right so we're going to get all

the blank stuff that we want so we don't have to like show an error or anything like that if it's nil so we want to make sure there is user data in our user defaults if there is now we do basically uh very similar to this do try catch except instead of encoding we're decoding okay so do and then we'll say user equals because we want to set this user equal to whatever we pull from user

defaults user equals try let me move this up again my head might be in the way try Json decoder right we're decoding from user defaults dot decode from and then we want to do user this is where you just have the actual type that you want to convert the data into and then what data do you want to make a

user out of well that's our user data that we have in there so here we type user data and then xcode selling me like my errors aren't handled because I haven't written out my catch block yet so now we want to do alert item this is if the decoding fails right if we try to pull out a user and we

can't do it alert item equals alert context dot invalid user data right the same error that says we couldn't retrieve or save okay now when do we actually call this retrieve user um because on Save changes right we do it you know when we tap the save changes button we already had set that

up if we go back to our account view see on the save changes uh button here we have viewmodel.save

changes so that's when we were calling that well on the retrieval we want to call on appear so in our navigation view here above the alert we can do dot on up here and then here we do View model dot retrieve user okay hit resume make sure everything's good to go so now because we have

already saved the Sean Allen user in user defaults it's already there we just haven't retrieved it yet so now as soon as this screen appears viewmodel.retrieve user is going to be called and then on our view model this is going to run we're going to make sure we have data in there again in our case we do have data because we already saved Sean if we hadn't saved Sean in there yet then you

know this would return nil nothing would happen you would just get the default user so if we have data in there we're going to decode that data into a user and set that equal to our user which again the user is published so when this user object changes by getting set to something else published means it's going to broadcast its change and then our account view listening to that change will

trigger a view update and populate the new data and then of course if we can't decode that for some reason we're going to show the alert context invalid user data okay so let's run this and test this out okay so let's tap on account and there you go Sean Allen all my stuff is there April 14th my extra napkins and frequent refills right so now our user data is persisting in between app

launches and the thing to remember about like user defaults is if the user deletes your app right they just get rid of it then user defaults will clear as well so the stuff you want to store in there you know make sure it's not something super super useful that if the user deletes the app you know they never have that again because user defaults gets deleted when the app gets deleted

okay so that is data persistence with app storage and user defaults again app storage was brand new in iOS 14. it's basically just like a state variable that watches user defaults and again the disclaimer here is you probably don't want to be saving your real user and user defaults for reasons like I said usually a user object is much more complex than this so it's probably

too complex for user defaults and you know if the user deletes their app they delete their user so you want to keep your user on the server but again you know it's just just an educational example of how to store a custom object and persist the data in between app launches in this video we're going to build the UI for our order screen and here's the quick challenge as you

see here it's a relatively simple list may look familiar and we have a button that also may look familiar so the point of this screen was for us to start using our reusable objects right that's kind of the lesson I wanted to show here so that's my hint I'm gonna see if you can build this yourself uh the little trick here is we're going to do the swipe to delete so that's the new little wrinkle

but if you want to try to build this yourself again it's mostly review but we're using reusable objects so uh give that a shot if not that's cool we're going to build it now but I always like to give you the opportunity to you know try and push yourself okay so into our code here the order view move move it up here let me minimize these folders because I don't want my head blocking the way here

so screens uh we are in the order view which is nothing right we just have the basic placeholder that we had now again pulling up the design let's kind of break this down a little bit it's a list view but there's a button at the bottom so that's going to be a v-stack with the first View at the top of the v-stack and the button at the bottom of the v-stack so pretty simple layout so let's

build that basic structure so first of all let's in the navigation view build a v stack and put or put the text in the v-stack so xcode doesn't freak out you gotta have something in there and then we'll put our navigation title on the v-stack okay so nothing should have changed but we just put a v stack in there so instead of text and

orders uh let's create a list now we got to do this list a little bit differently because of the fact that we're doing swipe to delete the on delete modifier we're going to use is only on for each like it's only a modifier for that like list doesn't have an on delete modifier so something to keep in mind uh if you do want swipe to delete on your list you can't build lists how we've been

doing it where we initialize the list with you know our our data and then ID and all that stuff you have to put a 4-H Insider list which is also another common way to build this anyway so you should be familiar with both methods so we'll type four each and then we'll initialize it and the four each has a similar initializer uh to just our list right where we have our data which is unnamed

that's that underscore ID and then content so it's it's pretty similar to how we used to initialize the list so it's not a complete departure from what we've been doing okay data we need to adjust this a bit so let's go to our appetizer right this is where we have our mock data uh we have our sample appetizers but so we have an array already that we can use however if you

remember what I said that this sample data is a little messed up because uh our ID is what matters it's how swift UI knows what object is what and right now our ID is the same for everything and this only comes into play when we're like adding items to an array or deleting items from an array which is what we're doing in swipe to delete so we need to create some different dummy data to

create our UI so I'm going to copy this here and basically we're just going to create three items and they're just going to have different IDs that's all so down here we'll do order item one tap that over if you have to tap this over and Okay cool so now instead of zero

zero well we can keep the zero zero one we'll do copy paste and paste again just three items here so two and all we're really changing is the ID so they have unique IDs and then three get this back three lined up okay so again instead of id1 we want id2 instead of ID one we want ID

three so again just unique IDs you can change the name if you want in fact let's do that test appetizer one just to be sure you know we have the uh the right items here three and then four I'm dumb I forgot two I can't even count two and three okay so it doesn't really matter we

just wanna make sure we have the different items uh and then now we'll create a an array called static let order items and that is going to equal order item one order item two order item three and again this is just building out some quick dummy data that I use to build my

uis of course we're going to populate this with real data you know eventually but to get the UI going in the structure of it um you know this is what we want to use so again it's going to be mock data dot order items and that's going to be our array of order items one two and three so

back to the order view that's what we're going to use here for data so mock data dot order items the array and then the ID would be the keypath ID but remember we don't need that because we're conforming to identifiable on our appetizers and then the content you know we don't need we can uh do our viewbuilder here and this is where our cell would go and oops I forgot again the same

way we do it we need appetizer in right because as we're iterating through we get an appetizer for each thing now I need a something to return here as the cell and like I said we're going to be using the reusable objects here so this is going to be an appetizer uh list cell that we've already created remember that takes in an appetizer and we'll pass in the appetizer so again very very

similar almost exactly what we did before on our list view except now we're using for each instead of uh you know doing it on the list try again on the preview there we go okay you'll notice something different like our list looks funny so here's what we have to give it a list Style so on list you can do dot list style and here's where you can do a couple different ones there's

plain list style so if you initialize that now that's going to look like our normal list however kind of the the new hotness in iOS is the grouped list style so this is where you would just do group list Style and this is what gives it that kind of uh new look or you can do inset grouped list style I guess this is what I was talking about when I was talking about the the new look

of list not grouped I I just forgot the inset part right how table views now are kind of like you know they got that padding on each side so if you want that style cool we're gonna go with the old uh plain list style I don't know I still like this like I like the insect grouped for like settings I don't think it applies for every type of table View uh so painless Style

so now that we have our our list now we need our button in the v-stack so uh button again the first closure is going to be what happens when we tap the button for now we're just going to type or print out order placed we'll obviously be implementing that later and then the label the second uh closure and the multiple Trail enclosures is what the button looks like and

what our button is going to look like if we go to views we have an AP button great AP button again this this was all about kind of reusing the objects that we've uh used so for the title again the string we're going to pass in right now is just kind of a placeholder we'll fix this once we actually have the value this is we're going to have our price total and then place order so

we'll say like you know uh 99.99 place order and you know later on we're going to write some logic that will calculate the total of our order but for now again as we're building the UI that's what we want now to me that has hugged up a little bit too close to the bottom so we're going to add some

padding bottom so dot padding dot dot bottom and then we'll just give it uh 20. question mark who put the question mark on the teleprompter who gets that reference 30. sure 25. again you can just dial it in however you're like well we'll stick with 25 put whatever you want in there to get the look you want okay so the UI is done you can see pretty simple right we just had the v-stack

our v-stack holds a list and a button our list is just another version of appetizer list sell except it's going to hold our order items in in a later video we're going to create our order object that is being manipulated you know when we when we add an item to order when we delete it that's coming later for now just for the UI we have our mock data again we're showing the list reusing the

same cell that takes an appetizer and shows the pertinent details uh we went back to our plane style list and then we added our button which again reused our AP button so we have it nice and simple and we'll calculate the price total you know later uh yeah so our UI is pretty simple now let's implement the swipe to delete this is kind of the new twist we haven't done yet now like I

said the the on delete modifier is only on the four each and it comes with some special features for that reason right this is why you can't use it like everywhere so if you do on uh Delete here you go perform and you can see we get an index set and I just realized that I need to actually create

a variable for our mock data array so we'll do at State private uh VAR we're gonna have to do this anyway when we actually had our order items but we'll need this uh now so we'll say order items and that is going to equal mock data dot order items so instead of mock data.order items for our

for each we can just say order items now I know you may be thinking well it's the same exact thing well we need access to our order items elsewhere so that's why I did that like specifically here so here we can do order items.remove and then not just at we want to do at offsets which is kind of hidden down here so remove at offsets and then you see at offsets takes in an index set well

good thing we got an index set right here so here we do index uh set so what's going to happen when we swipe to delete it's going to know the index of the item and then we're going to call order items.remove basically at that index so our swipe to delete should be working so let's run it on the simulator okay go to our order screen which is new okay so swipe there we go delete appetizer

one goes away appetizer three gone appetizer two gone we haven't put an empty state yet we're gonna do that in the next video but that's where we would show the empty state so our swipe to delete uh is working okay back to our code we'll stop this there is a little a bit of a cleaner way to write that but I wanted to show you how to use it uh when using just like the autocomplete that

you get because I feel like this spells it out a little more and is a little easier to understand how it knows the index set that's why it's got to be on for each so it knows you know this index um but we can write this a little cleaner by adding a function here so let's do func delete items

at offsets and it takes an index set remember we got that's the index that we got and then here we can just call order items the same thing we just called basically remove at offsets and then we pass in offsets and then now again this isn't as straightforward as this right because you can see hey you get an index that cool I'm going to remove that index set

um but it is cleaner that we can write uh just on delete perform and then instead of all that we can just call delete uh items we don't even need the at and there we go let's test this again just to make sure it's working go to order swipe to delete swipe to delete delete cool so it is still working

so again the first way was just to really spell it out uh this way is just cleaner but that wraps it up for our order uh view UI again and then in the next video we're going to create that empty State that's a pretty simple uh video but then after that we're going to create our order you know object that's in our environment that we can you know add items to the order delete it on our

order screen all that good stuff that's going to be probably a couple videos so let's move on we left off last video getting our order UI in place but what do we show when they haven't added any items to their order or maybe they've deleted all their items from the order well that's what we're going to create this empty state that you see here on the screen now empty states are very common in

apps right anytime you just have a empty data you don't want to just have a blank screen you want to have a nice you know graphic and a message letting the user know what to do you know to populate data on this screen so we're going to make this empty State reusable to where we just pass in an image

and a message that way you could you know change the image in the message accordingly so here in our views folder hit new group uh we'll call it empty uh States because you know you may have a different style of empty States throughout your app you never know uh so a new file in the empty States it's going to be a swift UI view hit next we're going to call this empty state

create cool here we go resume on the preview just to get the basics up there great now pulling up the design it's a real simple View and it's going to be similar to what we did on the spinner view how we had a a color as the background and that background is going to be system background in a z-stack forgot to mention that right the background is the z-stack on top of that is

going to be our v-stack that holds our image and our message so that's the the basic structure so to start that let's do a z-stack around our text hello world this is what happens when you have two views out there you get all those two previews so uh again nrzstack the first thing we want to

have is our color and we want to initialize that with DOT system uh background because again we want this to be black and dark mode white in light mode and we want to make sure we do dot edges uh ignoring safe area dot all and the reason being say instead of system background we just did blue right well we have we are ignoring safe areas let's let's comment that out and you can see right

we want it to fill the whole screen we don't want it to look weird like that so I know that's review but I like to reiterate so that's why we want to do edges ignoring safe area and Dot system uh background for our color so that is the base layer of our Z stack right our color so on top

of that color we want to have a v stack for our image and our message so v stack and image what image do we want well it doesn't exist yet so we need to add that image so on your XC assets and by the way the image it'll be called empty order it'll be attached to the video so download that

image drag it into your XC assets like I'm about to do right now so in finder we have empty order PNG drag that in and then you should see this little list receipt type looking thing so go back to empty State and the title of the image is now uh D order and quotes hit try again on the preview

hit resume on the preview there we go just like all of our images super large right we need resizable we need to do all of our typical image stuff here so here we'll do dot resizable dot scaled to fit and now we want to give it a specific height the width doesn't matter because

it's more of a vertically oriented image so we'll do frame with a height of 1 50. I'm sorry that was width I want height of 150. got to be careful so we can delete the whole width because we're going to leave that nil delete the alignment and we're good and that's just a styling choice if you want

your image to be super huge and fill up the whole screen go for it I like the I like the minimalist feel so I don't like it to be too big but our image is set up now we need to set up our message which is a text so if I go text uh with a string let's say this is our default message we're gonna

we're gonna fix this later but we just again we're working on the layout let's do font and we'll do Dot title three maybe we're going to kind of play around here okay title three uh font weight of that semi bold and this message could be long so we want to do multi-line text alignment Dot Center

so if it does line wrap we want it to be centered not not left or right aligned and we do want the foreground color to be dot secondary we want it to be this like gray color and then for my taste it's pushed up a little bit uh too close to the image so I want to add some padding all around because

I also don't want the message to go all the way to the edge of the screen we want some padding there cool that's the basic structure of our empty State now let's make this reusable like I said so our empty state is going to take in uh two parameters it's going to take in let image name equal or I'm

sorry BF type string and then now empty order will be image name and then our message is also going to be a string so let message equal string and then okay default message will now be message okay so that's how it's reusable when we create our empty State we're gonna have to pass that in which again our preview is going to have to take that kind of stuff too so fix the image

name here will be empty order the string will be this is our test message I'm making it a little long long for testing hit resume and you can see how our text now wraps it's centered we got

the padding so it doesn't go too far and if you wanted to just a little I like to do this with my messages right I don't like how the period is right there this is a little sidebar I like to do you know forward slash n uh to add a line space you can kind of break the line at the period right

this is our test message I'm making it a little long for testing I usually like to do that I find that easier to read um just a little small tip so now that we got the view built let's actually uh you know put this into action here so on our screens let's go to our back to our order view now

so we're gonna do something similar to what we did on the loading view right we're gonna we're gonna smack this empty State on top of everything if uh basically our order items dot count equals zero or we're going to use is empty but that same idea so now we want a z stack as our root and let's drag

everything the v stack here in there and our navigation title is on the Z stack so the the base layer of our Z stack right is the the v-stack that we've already built the list and the button again we want to smack the empty view on top of that so that's the top part of our v-stack here

so moving up here now we want to do if order items dot is empty so we only want to show this if order items is empty and then now we'll show empty state right but empty State takes in two parameters the image name in the message so the image name is going to be empty Dash order and then the message

will be you have no items in your order please add in appetizer okay so to run through that one more time when this redraws right and it's going to redraw at the moment every time our order items change so because we have this mock data in here the first time you come here there's going to be

orders in there because there's mock data but once we're done building like kind of the real functionality until they've added an order we're going to see the empty state but for now the only time we're going to see an empty state is if we use our on delete right we swipe to delete three times then order items will equal zero this will redraw it's going to go into this if statement

because now order items is empty it's going to smack our empty State on top of everything showing the our empty State view in theory let's run it and see if it works okay so going to our order again this is our mock data if we didn't have the mock data we should see our empty State here because order items would be empty okay swipe to delete gone swipe to delete gone Moment of Truth

so as every time I swipe to delete our order items is changing so it's triggering a view redraw so now when we trigger The View redraw order items are going to be empty we should see our empty State there we go that was a little fast because I didn't get a chance to delete but yes you see our empty State now you have no items in your order please add an appetizer and again here's another

example I didn't do the the forward slash n here to you know make that please at an appetizer go to the next line we're going to do that real quick so down here slash n there we go that just looks a little neater hit play order again we'll test this swipe to delete swipe to delete swipe to delete cool now our empty State shows you have no items in your order please add an appetizer

now for my taste again this is purely subjective this feels a little low on the screen even though it's centered back to what we talked about how like it's only centering from the navigation bar down right so it looks lower than centered so I want to bump it up a little bit so we're going to talk about a new modifier we haven't really talked about yet at least I don't think called offset so

we'll stop this go back to our empty State and we're going to add an offset to our v-stack to push it up just a little bit so we can do dot off uh sets and you can see it takes an X or a y we don't care about the X we want it to be centered we just care about the Y so we need to give this a

value that will push it up a little bit all right so resume on this get rid of that so we can see this in action so put 10 in there but a positive number will push it down like let's use 100 right see how it gets pushed down uh we use 200 right to really push it down but you can see the frame

of the things still there is just pushing it down a little bit we don't want 200 we probably want like negative 50 and again this is me just playing around and that to me looks good again we're just bumping it up just a little bit let's run it to see it with the uh the navigation bar in place to

get the real the real deal look here right delete delete delete that's okay perfect at least for me for my taste right it's just like a little above Center I feel like that looks uh really good for an empty State and that was just a quick uh introduction to offset again you can kind of nudge things left or right up or down by using that offset there okay so our empty state is in

place let's resume this here uh let's move on to actually you know building this order object so we can get the functionality again where on the the home screen where we're adding appetizers to our order those orders that we add are showing up in the order View and then you know we can swipe to delete our total is going to be calculated uh all that good stuff to really bring this app together

in the last video we added a bit of Polish to our app by adding this empty state for when our order was empty but up until now we've been faking our order right with some mock data well in this video we're going to create our order object that's going to go into the environment new topic brace yourselves uh that way multiple screens can access it you know for example we add to our order

from the appetizer list view more specifically the details screen and then we want whatever we added to show up on our order screen and then we can also remove items from that array on our order screen so the main topic of this video is creating that order object and then using the environment now before I explain the environment let's actually create that order object so in our

model do command n for a new file it is a swift file hit next and it we're going to call it order and it's going to be very similar uh to our view models so the difference between view model and the environment like overall the concept is kind of the same however our view model is very tightly coupled with a specific view whereas an environment object isn't attached to a single

view like I said multiple views can access it depending on where you set it up more on that later I don't want to get ahead of myself anyway back to this order object so we do want to import Swift UI and like I said this setup is going to be very similar to how we set up our view models make my font a little bigger I noticed in editing my font was kind of small sometimes

anyway final class order and it is an observable object again this is the same setup as a view model because again concept is the same we want a published property on this and we want to have an array of appetizers right that's the the items on the order right for adding multiple appetizers

we're very hungry you know we need an array of appetizers so let's do at published so again this should look very very similar to a view model uh VAR items and items is an array of appetizers and we're going to initialize that with an empty array right because when we we fire up our app we have no orders so again the setup is like exactly like a view model for this part of it however here's

where it is different now that we have our order object we need to inject it into the environment somewhere and here's why the somewhere matters that's how you dictate what has access to your environment object think of all the views like Downstream or all the child views are the ones that are going to have access to our environment object so pulling up this little visual here in

our example our app is kind of laid out like this right we have our tab View and things like the appetizer list view the account View and the order view are all children of that tab view back to the code let's look at that go to screens scroll up appetizer tab view get rid of our preview we don't

need that look see our tab view or appetizer tab view I'm sorry is the name of the view and you can see the appetizer list view the account view order view Etc are all children of our tab view so if we put our order object into the environment at the appetizer tab view level again think of it as like flowing Downstream all the child views so that means appetizer list view will get access to that

environment object account view will get access to it oh order view will get access to it and then all their child views right so when you inject something at like the very very top level you can consider that as like everything in the app is going to have access to that now you may not always want that in our case we do right because you know our appetizer listview is going to change

uh stuff in our order our order view is going to change stuff in our order our account view is not but that's fine but you can see how our entire app will have access now when I mentioned that you know you can give certain views access depending on where you inject it into the environment well we just gave the example of injecting it at like the top level well let's say our account view

like our settings or whatever was actually more complex like here's a visual example of the Apple settings you can see as I'm going deeper into these settings like I'm like four screens deep into my my settings or if you can imagine this is our account view so if you can imagine injecting something just at the account view level into the environment now our whole app doesn't have

access to it but all the the settings child views again if we had a very complex setting set up like apple does all those child views again all the views Downstream have access to that environment object and that could be something like a settings environment object right so the main takeaway here is where you uh put your object in the environment matters because only the child views of where you

inject it are going to have access to it so if you try to access something that's not in that view hierarchy your app's going to crash in the review section coming up later in the course we're going to do a deeper dive into some more examples of that but that is the overview let's get back to our example where we're injecting it at like the very top level of our app so all of our views have

access to it so how do we do that right you may think do it in this appetizer tab view but no you want to go to our app lifecycle actually right remember this we went over this appetizer.app

because this is where we're first initializing our appetizer tab view so when we initialize our tab view we want to initialize it with an object in its environment right so again the very very top level so we can do that by creating an order object on this app here struct so VAR order equals and we're going to initialize a brand new order right and if we go back to our order just to

double check right we don't have an initializer so when we create our order it's basically just going to get created with an empty array of appetizers so back to our app view here so now we need to take this order that we created here it actually inject it into the appetizer tab views environment now there is a modifier for this so we're just one line so dot environment object here and then

we want to pass in the order that we created so do command B there we go so the order that we created here on line 13 we are injecting into the appetizer tab views environment so again all the child views of the appetizer tab view are going to have access to this order object so I just said they have access to it but how well let's go to our appetizer detail view this is the first spot

we want to use it right because if I pull up the canvas right when we tap our add to order button right we want to add it to our order object so here we are in our appetizer detail View and in order to get access to that environment object it's a property wrapper at in by run mint object there you go VAR order and it is of type order now let's talk about this real quick

because there's a there's kind of a gotcha right we're not like setting this equal to anything we don't have to initialize our appetizer detail view with it you know like like for example how we have just our appetizer when we don't give it a value you know it's going to say hey add this to your preview or you have to pass in a value it won't let you do that the environment object

is different because it's assuming that because you did this if something is in the environment and it's just going to pull from it so this is where your app will crash if you don't inject it into the environment properly right like we said only the child views have it good thing appetizer detail view is a child view of the app tab view because we put at the top level but if you were

getting more specific with where you put your environment this is where you got to be careful because again if appetizer detail view was not not in the view hierarchy of our tab view this would crash because there's not going to be anything called order in the environment okay luckily for us there is so now we have access to this order variable that we can use so where do we want to

use it well we want to use it when we tap on the add to order button so that is down here right now we're just printing tapped well let's do order well we want to add the appetizer so order has a variable called items right just to verify that let's go back to order there you go yep our variable called items is an array of appetizers so we're going to append uh our appetizer to

this items array so dot items dot append new element and then we want to append the appetizer in the appetizer we have is the appetizer we passed into this detail view like from the very beginning right so we know we want to add that one to it now this is a fine line of code it's not super hard to read I don't know I like to refactor this a little bit further this is

completely subjective if you don't want to do this don't worry about it but I also like having you know functions on my my order object here so in order I'm going to write a function so we'll do uh Funk add and then we won't give it a name but we'll give it a argument label Appa

Tizer and his little type appetizer and then here I'm going to do items.append appetizer with whatever we pass in there so again this is just a very very small refactor but you'll see at the call site how it makes it a lot more readable even though that line of code was fine right so and real quick you'll see why I'm not going to give it a name if you don't want to give your

your functions like a parameter name you use that underscore there and then you can use this to use like within the scope so you'll see why I did that here in a second if you're not already familiar with this technique so appetizer detail view instead of order.items.appen you know let's just do order dot add and you can see uh I get this and here's the reason why I didn't name my parameter

is because it tells me I need an appetizer of the type so to me that is letting the user of my code know hey it expects an appetizer rather than just like naming the parameter appetizer and then passing in an appetizer a little bit redundant so here I can just type in appetizer right so order.ad appetizer I like the way that reads just a small little side rant on you know refactoring

order.ad appetizer I like the way that reads just a small little side rant on you know refactoring in code style okay so what's happening here right on our detail view we are basically getting access to our order that's up in the environment right and the environment is kind of like Global across our whole app so we're getting access to that in our detail View and then when we tap the button

that order that's up there in the environment we're adding this appetizer to that order right in the items so now that our order has the item we need to read that item in our order view right so let's go to the order View and I'll minimize all this stuff so my head's not in the way okay let's hit resume here to see our order view cool here we can get rid of this mock

data right we don't need this at State private VAR order items okay what we need access to is our environment order that has items so at environment object VAR order of type order cool so now anywhere I was using those order items I can now do my order dot items right because

that's items is the array that's on my order object so instead of order items order dot items and then same thing here cool to command B you should be good to go cool so now now that we're not using our mock data anymore right so this should be empty if my preview ever works okay the preview hates me that's fine we'll use we'll use the simulator but so now if you can see what's

going on here right I'm getting access to the order that's up in the environment in my my table view now I'm reading that order object in whatever array of appetizers is on there that's what I'm going to show in my table view same thing for delete items right delete items is going to remove items from the order dot items right so we're just accessing that order a little bit of refactoring

thing same thing here we're just checking if my order dot items is empty before we show the empty state so let's run this on the simulator and uh see if this works okay here we are we should see an empty State when we tap the order there we go empty State home okay let's add some uh let's add these stuff shells again these are my favorite on here I think okay add to order okay we should

probably dismiss this so let's let's go back and update that later but let's close this out our stuff shells should be in our so let's click on order bam stuff shells nice you'll notice our price isn't updating we're going to fix that in a bit but our order is updating right we added something on our home screen or our appetizer list View and it showed up in our order because

again that's what the environment object does your screens have like Global access to this item and then likewise I can still delete from there we see our empty state right we're just manipulating that order that's up in the environment so cool that's kind of the basics of using the environment object let's let's clean this up a little bit though like I said if we go back to our appetizer detail view

we want to dismiss the view so we'll do is showing detail equals false so we'll dismiss the detail view after we hit add to order and we can optimize that even further for just user experience we'll handle that in the optimization section so let's test that real quick just to be sure cool we'll add chicken fingers to the order add to order and that dismisses and you're

back shopping okay and let's double check the order yep chicken fingers are there great now another thing I want to clean up in the order view is this delete items right because again I like to have these functions like on my object that it's manipulating because like we're only deleting items like from that order so I'm going to actually command X to cut this function go to

my order just like we had add here we go we're going to have a delete items right instead of order dot items it's just items right because items is right here already on the order and then back in our order view instead of just performing delete items we perform order dot delete items and again as always let's test this real quick to make sure we don't we don't break anything

let's add chicken avocado spring roll add to order cool there's our chicken avocado spring roll and we deleted I just did the fast too too long of a swipe that's why it looked weird Okay so the last thing we want to do if you notice our price wasn't updating on the button so we can write a function on our order to calculate that and this is going to be a computed uh

variable because this is going to get you know checked and computed all the time so we'll do VAR total price and that is a double and that's going to return we're going to use items dot reduce zero and then the closure here is going to be a dollar sign zero plus dollar sign one dot price so basically what we're saying is here here is go through the entire array and add as you go through

add all the prices up to one total essentially if you're not familiar with higher order functions and filter map reduce I don't want to derail this because again I was assuming some Swift knowledge but I'll link to a video I did on it a long time ago and some other resources in the description but what this is going to do is it's going to basically add up all the prices in our items

array to get a total number so where do we want to use our total price variable well that is on our order View and you see here our AP button and like I mentioned we're just hard coding the 99.99 right just to set up the UI well now we want to replace 99.99 with our order dot total price

so again string interpolation order.total price and remember we gotta do the specifier specifier percent dot two F and that'll give us our our decimal places right we want two of them so now let's run it and test this out and I'm going to add like multiple items to the order you know just to show the total so Asian flank snake 8.99 sounds good mozzarella sticks 6.99 sounds good

jumbo tater tots yes meatballs yes damn meatballs are expensive all right anyway order cool those are all four of my items you can see it tallied it up 42.96 and then watch as I delete it like I'm you know 13.99 for tater toss that's insane let's get rid of that cool and you can see my price calculated and updated accordingly and again back to the environment object that is

because anything that is like listening to this and what is listening to this well our appetizer detail view is listening right the environment object and then our order view is listening right the environment object so any of these views that are relying on this order object when our order changes the UI for those views will also update again back to the big picture of Swift

UI remember Swifty is all about having one source of Truth and then setting up your UI to react to whatever that source of Truth changes right the data so when the data which is our order changes our UI is just going to react to whatever our data says right that's Swift UI in a nutshell and back to the simulator here uh just to finish this out right get rid of the Meatballs okay man

15.98 cool mozzarella sticks so it should see 99 done and then delete again now we're back to the empty states you have no items in your order so our order is functioning we injected it into the environment at the top level so all of our child views have access to it that is the the basics of environment and in the review section of the course we're going to do a deeper dive into the

environment to talk about other situations or examples on when you might use it but something like this having an order or a cart you know on an e-commerce app is pretty common so this was a good example to get you started because even in those other examples the concept is the same wherever you inject something into your environment all the downstream views all the child views are going to

have access to that anything that's Upstream from that view will not have access to that so if they try to access it it'll crash okay that actually wraps up the appetizer app right everything is functioning the home screen the account the order we're going to come back and tweak some things in the optimization section but overall the base functionality is done right so let's add

something to order real quick give us those tots again you know in a real app when you hit place order right this would send up a network call you know to place the order do all that stuff of course I don't have a full backend database all set up for this but you can imagine that's what would happen there um but anyway hopefully you have a good basis to explore with this app

start you know trying to add features to it or change the design or just use this as a basis to play around with and I hope that's what all of these apps over the past you know 40 videos have given you just again a basis to play around with and explore as you learn Swift UI further now it's time to update the appetizers app for iOS 15. and because this app was much bigger than our

previous apps this is going to be broken down into I'm not sure exactly how but you know five six videos so the source code for all the updates is going to be attached uh to the end of the last video just as a heads up but I definitely wanted to break this up into a bunch of different videos

so it wasn't one Marathon video so to kick that off I'm going to start with how I actually update an app with a new iOS 15 version comes out so the first thing I do is I open up the app and I want to run it on iOS 15 to see if there's any errors or warnings in my code see if the UI is acting

weird anywhere and then I fix all that stuff just get it running in iOS 15 and then you start adding the new stuff and refactoring the code all that stuff so this video is going to be the initial run of the app and see how bad iOS 15 messed up our app so first things first in appetizers and

by the way this code I'm starting with is the last source code on the last video we finished the iOS 14 version of the appetizer so this is the source code from right before the iOS 15 updates so click on the appetizers app hit the appetizers project again iOS deployment Target make that iOS 15 and

then in the project iOS 15 and then while we're here not iPad not landscape left not landscape right maybe you've played around with that looks like crap on the iPad looks like crap in landscape that's a little bit beyond the scope of this course but if you want to you know take these projects and run with them maybe getting it worked working in landscape is a good project maybe

getting it working on the iPad is a good project as well but we're not going to mess with that okay so now that we've done that I do a command B to see if there's any errors or Warnings see I got build succeeded no errors no warnings now that in a in a bigger like quote unquote real app that is

going to be pretty rare the reason we don't have any warnings is because this app already had a minimum Target of iOS 14 so it's not like it was an older app if you've been working on an app for years you know maybe since iOS 11 than iOS 10 you know you're going to have older code that

the deprecations are slowly going to catch up with you and it's going to be a bigger code base so I just want to set those expectations when you're in the real world that uh anytime a new iOS version comes out if you're working on an app that's been around for a little bit you're going to see a ton

of warnings and errors that you have to fix we don't have to do that because this is a relatively simple and new app but again going through my process cool no errors no warnings let's run it on the simulator and see uh if the UI is messed up at all okay here I'll go back to light mode you can see our table view or list sorry got inset by default that must be the new default in

iOS 15. now if you want that you like that look cool you don't have to do anything I'm going to

iOS 15. now if you want that you like that look cool you don't have to do anything I'm going to go back to the look that we had before which if I you know let's practice adding something to order add to order cool now if I go to order you can see this the list style I just like the way

that looks better in this circumstance so it's fine on our orders but on our home screen it's not fine so okay we're gonna have to fix that and obviously adding to an order worked account every thing looks you know good there well I always test like you know let's add an account Sean

Allen you know me at email.com birthday cool it's not my birthday obviously napkins save changes profile saved okay that seems to be working so so like I said I just run through the functionality of the app make sure things are working fine so that account should persist right so I'm going to stop running it running again just to make sure my persistence is still working my

account still shows up cool okay so the app seems to be working the only issue we have here is this list inset that's on by default so let's fix that real quick so we'll stop running that get rid of that go to appetizer list view hit resume here I think yeah we just see the loading screen here but

here's our list on the appetizer list view so in order to get that plain list style a modifier on list which here's our list we can do this we'll do it below the navigation title we can do dot list style you can see we do dot grouped inset inset grouped plane sidebar I believe grouped is what they have that's the default but I want to do plane right that'll give me back my plain

list so if I run it again we should see this yep there's our list looking like it used to Okay cool so that's fixed the next step I do is go through known deprecations if you watch the weather app update I talked about deprecations I'll give a quick 20 second review but deprecations are you know when Apple decides to change Swift UI and the syntax and the way they do things so they'll

deprecate the old code which means it's no longer going to work at some point in the future and they'll give you a new way to do it now luckily they usually give you a couple years to do it right they'll first tell you it's been deprecated then maybe a year later they'll start putting up warnings in your xcode and then maybe a year later they'll like make it not work anymore so you have

plenty of time and like I said before how do I know about these deprecations you can look at the xcode Beta release notes so during the whole beta period of xcode from June till September you can follow the release notes to see what's been deprecated but it's usually a lot it's a lot to keep track of people are talking about them on Twitter usually during that time period I'm like

making a list of what's been deprecated and then when I go to update my project I go through that list and I search for that stuff for example like we talked about before or I know edges ignoring safe area was deprecated so I typed in edges Okay cool so let's go to this Edge is ignoring safe area I know that is now dot ignore safe area and then the next place I'm using it is down here

cool so like I said part of the process I go through and try to fix all the deprecations that I know of and I say that because it's not the end of the world if you let some slip through like I said that edge is ignoring safe area was actually deprecated in iOS 14 and I missed it for this course not a big deal you see the app still work fine it still worked like I said

Apple gives you a couple years they don't just change the code on you and break it right away sometimes but that was one of them another one I know of was accent color now what accent color am I talking about here so let's go to our appetizer tab view this accent color which was you know the brand primary which is what makes our tab view the bottom of the tabs that color cool xcode

does not like this part okay so you can't see the preview of the tab but you know the tab colors are brand primary uh xcode crashes gotta love it right anyway this accent color has now been deprecated and if you option click on it you know you can go to the documentation and you can see uh deprecated over here on the right so the new way to do this is if you go into assets

you can see accent color here is now moved into the assets and you would create something just like you did brand primary for accent color so let's create that so I'm going to click on brand primary open up the right pane here click on the color and you can see here's the 8-Bit hexadecimal you see content srgb so I'm just gonna copy that hex and then go to Accent color

Universal make sure you do a pre appearances any dark so for any appearance uh again the color what we did we did srgb and then we did 8-bit hexadecimal and then paste that into there and then we'll do the same thing with brand Primary in the dark there might be a quicker way to do this I'm happy to hear it and then for dark you see we're doing display P3 let's go back

to srgb and then let's go to 8-bit hexadecimal and you can see here's the 8-Bit hexadecimal copy that go to Accent color in dark again content srgb not floating point we're going to do 8-bit hexadecimal and then we'll paste in that hex code hit return see we get the same color so now that's the accent color for our app so we no longer have that in our tab view so if I delete this code

xcode crap that doesn't like this preview I'm getting rid of this preview um you know brand new xcode 13 you know you're going to have issues here okay so delete that accent color now run it on the simulator and we should see our tab view still working as expected right we just deleted that code accent color yeah so you see our bottom tab we have that dark green

if I do command shift a for dark mode you can see we get that brighter green uh down here on the tap so cool that is still working accent color again minor language deprecations you're going to see especially early in Swift UI as with UI matures you know you're going to see these deprecations less and less but in the early days of Swift UI this is kind of the norm every time a

new iOS comes out so always look for deprecations that's another phase of the initial getting the up running in iOS 15. so now that we have no warnings or errors in our code we fixed deprecations we fixed any iOS 15 UI bugs now it's time to actually start adding the new stuff all right let's go in this video we're going to make some small tweaks through our UI I'm going to show you how

to hide the separator lines in a list as well as change the color we're going to add a badge to our tab bar for when we add items to our order you can see that badge show how many items in our order we have that's a nice little addition and then I'm going to implement the new button system that we covered in the Frameworks app except we're going to write a custom modifier to reuse that on

various buttons okay so first things first the appetizer list view right so here it is it's the list of our appetizers on the initial screen so on each cell we want to change the separator so we'll do it above the tap gesture modifier so it's relatively simple right you can do dot list row

separator and you see it's a visibility modifier or parameter so you can do dot hidden automatic visible so you can do dot hidden and we'll run the app and you'll see our separator lines will be hidden on the cell I'll do command shift a to go back to light mode right see there's no separator lines purely a stylistic choice if you want that clean look there you go if you want the

separate our lines leave it in okay so we'll stop that so I'm just going to comment that out so you can still see the code but we can also dot list row separator tint right where you pass in a color so do that and we'll say dot brand primary right we'll keep the look going it's a brand primary

now when I run it you can see now our lines are green I don't think that looks great but I'm sure there's a situation where you'd want to color these lines or style them however you like you can actually make the lines different colors per item right like say our our appetizer here had like a color like a background color well the color you would pass into this list row separator

tint is whatever background color that appetizer had so it can be dynamic right some can have red some can have green again I think that will look pretty ugly but I'm sure there's a situation where that would come in handy so I'm going to leave that commented out because I don't like the way that looks but I'll leave it commented so you can see the code in the source code so that is

how you can adjust these separators give make that smaller now let's talk about the badges because I love how simple this is so back to our appetizer tab view I'm going to not show the preview because I kept getting the crashes as you saw but before we get to the badges I'm going to show you I can

clean this up a little bit just because I don't know I like the way this code looks better so you can make these a label so instead of having an image and a text that's pretty much what a label is right so you could do label again make sure you do system image name so same thing home and you'll

see how the code looks better so all I did was passed in the text here and then the system image name here same thing so we'll delete that and then when I see something like this again this is pure style preference if you don't like it that's fine but I like to make that one line just to condense the code and make it pretty easier to read here so again same thing label system image name account

and then person and you'll see why I'm doing this in a second well at least why I like this because we're going to add a badge modifier to our order View and then I like the way the the modifiers look when they're all like on one line like this again purely code style preference as you go through your developer career you're going to have many debates about like code style highly

highly subjective so anyway if you don't like this cool do you uh all right so label tab item there you go but now when I add another modifier this is the bad right super simple dot badge and you can see we need to pass in an integer right because we want a number on our little badge

now what integer do we pass in well I want however many items are in our order if we go to our model right in our order object that we have here right we have an array of items so I want to get the count of this items array and that's what I want to show in the batch now how do I get access to

this order uh if this is still fresh in your mind you just did the appetizers app maybe you know we used an environment object so if I go to my order view right you see we have environment object order in fact I'm going to copy this because we're going to need that exact same code and real quick refresher on environment object in case you're coming back for the updates or hey just repetition

right remember we injected this order if we go back to our app here like the the main route right at Main the main route of our app we created an order and we injected it into the environment right here so all of our views will have access to this order but to get access to it like we do in our order view we have to create an environment object variable called order right and that's

how we get all this information well because it's up in the environment like I said all views have access to this so if we go to our appetizer tab view now we can get access to it in our tab view right just environment object like we just did I pasted it in there cool now we have access to

this order so when I want an integer to pass in I can just do order dot items remember items is the array of appetizers dot count and if the badge is zero like if nothing's in there it just won't display like it's not going to display a zero so relatively simple now let's run it and we'll start adding some stuff to the order and you'll see the badge work magically like I love this Edition so

we're going to add Asian flank steak add order bam we'll get the badge on our order let's add chicken dumplings add to order so I'm gonna add a bunch of stuff real quick so you can see cool four items in our order and then another cool thing if we go to order uh I don't want the chicken dumplings

anymore let's delete that look at our batch went down to three look at our badge went down to two look at our badge went down to one and then our badge disappears because we have nothing in our order that is awesome with relatively simple code so that's our badge working now let's go to our button here right so if I go to views buttons right we did AP button very similar to what we

did in the Frameworks app remember how we you know passed in a title and had our styling like on the text right well what we're going to do is Implement pretty much the same thing we did in the Frameworks app for our button except we're going to refactor that out into a custom modifier so we can reuse that on multiple buttons I don't think we've covered custom modifiers in this course yet

so another nice learning opportunity so appetizer detail view let's get the preview out here so we can see what we're doing hit resume cool you see our button 999 add to order now if I go to the button down here you see we have the AP button where we pass in the title just like we did in the Frameworks app uh well no not just like it because remember we passed in a label so we could

have the little book image so we have to have the book and then learn more I don't necessarily want to add an image because we have the price here and then add to order I think it would look too close cluttered too cramped if we try to squeeze in an image there so instead of a label because we don't

want an image I'm just going to do text and then the string I'm going to pass in is the string I have right here so copy paste that I'm going to comment out this AP button here so now we should just see some very generic text down there so now let's start adding modifiers to our button so dot button style remember this is the first one this is the style that you're going to go with remember

border prominent was kind of the style we want I'm going to mix up the style a little bit remember I want to go border because I like that new tint look right where it's the same color button which is the tinted background so that's what we're going for again and if you skip the Frameworks app it just went right to this appetizers app if you're coming back to the course go back I

cover all this in depth here I'm just going to do it pretty quickly to get the style we want so I want to dot tint and then the tint is dot brand primary and you can see what we got working over here in the preview since I resume it there you go I'm going to click off the button so we get rid of

that red square for the padding cool if you like like that skinny button you're done again I like my buttons fat I like them nice and easy to touch so you can do control size and then we'll do dot large now let's run this app to see this in action because you're going to see how this changes with

dark mode too and I think it looks really cool in dark mode so let's see our button here cool that's our button command shift a to go to dark mode and you can see we still got that change in color and now those buttons look really cool in my opinion in dark mode so that's the style I'm going

for with my buttons but you'll notice we use this button again in uh well let me add to order here in order for place order we're using this button again well now we're like not consistent I want that same look and feel of the button so what I could do stop running I could just you know copy

and paste this and then paste it to my button in the order view but the reason you don't want to do that is because let's say we do want to change our button style well now I got to go to like every single button and make the change because I just copied and pasted and that can lead to errors

because maybe you'll miss a button or maybe you'll have a typo and one of the buttons and all your buttons won't be consistent so what we want to do is we want to refactor these modifiers away into a custom modifier that way on the button I can just put one modifier and say standard button style and I know it's always going to be the same and if that standard button style changes I can just go

into my custom modifier make the change there and all my buttons will update so that's the benefit of doing this so here in views right click a new file and I'm going to create a swift file here next and again this is Project organization but usually I just do custom modifiers because I don't usually have too many of these so I like have one file and you know if I have five or six

custom modifiers they're just all here in this file again if you use custom modifiers heavily maybe you want to organize a little bit different again that's project structure organization highly highly subjective so import Swift UI and I'm going to do a struct called standard button style and the reason I called it this well real quick this is a view modifier and the reason I

called it standard button style is typically in apps you have uh many different types of button Styles I don't know throughout the app so the standard button style would be like that's my typical button and if I had different buttons maybe I had like a checkout flow and I had like a checkout button style and that was different right you can see how you would label your button Styles

differently but we're going to call this standard button style so you can see I'm not conforming to the viewer modifier protocol because that needs a funk body you can see body content some view so content is whatever you're putting this modifier on so for in our case it will be the button but we just want to basically modify the content right which is some view so let me show you what that

actually means so when I go to appetizer detail view whatever I put this modifier on like you're going to see we're gonna put a modifier here the content would be the button because that's what the modifier is on so while I'm here I'm actually going to copy this I'm not going to cut it because I'm just going to comment it out again just so you can see the code in the source code and then I'm

going to go to the custom modifiers here and those are the modifiers that I want to put on this content right button style tint can control size Now button style can only go on a button so what's going to happen if I try to put this on a different view well these modifiers just aren't going to apply and it's going to be like nothing happens so that's fine so now what I can do if I

go back to my appetizer list view here right so the modifier I can put on I can do dot modifier and you can see this is where you put in your custom modifiers and I can do standard button style I'll initialize that do a command B and resume my preview and you should see that the button doesn't change it looks the same so now what I can do is go to my order view like where

this button is right instead of have okay app does not like previews xcode 13. just you know we all deal with these like bugs and issues so anyway here's the button here's the AP button that's the old custom button that we made well I don't want the custom button again I just want this to be a text and then the string I'm going to pass into the text is this one here same thing and comment

out the AP button and then here's where the power comes in right I'm going to do modifier standard button style and then now when I run the app my order View should have that button and again all I had to do is add my custom modifier so let's add something to the order cool check the order now it

looks like that as well so now you can see if you had a bunch of these buttons in your apps you just add that one little modifier to the button and you get your standard button style so it's nice now another way to refactor this I'm not a fan of this style but again style is subjective but

what you may see as well is if you I'll just do it in the custom modifiers real quick since this is just an example normally you'd want to put this extension in a new file so you do an extension on view or you do a funk and you would say you know standard button style and then it would be self.modifier basically what we just type standard button style so that's basically you can put this

self.modifier basically what we just type standard button style so that's basically you can put this on any View and the reason you would do something like this is so if we go to our appetizer detail view the button what was that warning oh I forgot to uh return some view yeah you need that for a

modifier so now when I go to the appetizer detail View and again this is purely code style you would just do dot standard button Style here's why I'm not really a fan is because this is just a function on a view like I could have put anything on that function yeah I named it standard button style I don't know I like the fact that I have to type dot modifier so I know in the reader of

my code knows hey this is a modifier right that's all this is is a modifier or is this you can have other stuff in that function who knows what it does even though if you named it properly like standard button style you know you're just styling the button I'm really splitting hairs here but I think it's a good discussion on you know just code style and and why people like certain things

right this is cleaner and if you name it right it probably could but I kind of like the fact that you know this is a modifier just my my preference there but I'll just I'll comment that out so you can see both ways in the source code but that is our buttons now working with the new iOS 15 button system we also talked about showing and hiding and colorizing the list separators and we added

our badge which I think is really cool that worked pretty flawlessly with very minimal code in this video we're going to work with the new at Focus State Property wrapper for Swift UI introduced in iOS 15 and we're going to use this to improve the ux of our keyboard so you can just navigate through our account view form pretty easily by just tapping the next button on the keyboard

so here I am in the account View and again just continuing on from the previous video so the first thing I want to have is at Focus State private VAR and I will call this focused text field because we have more than one text field right we have our first name last name and email so I need to keep

track of whichever one is focused and what I mean by focused is which one they're tapped into with their cursors at and with the keyboard is you know inputting to so Focus text field I need to keep track of that you might think oh this is going to be a text field but no I need to create an enum

to help me keep track of that so I'll do that real quick down here so enum we'll say form text field and that will be a case of first name name last name email right those are just our text Fields so now our Focus text field is of type form text field and you're going to see how we utilize that

in a second if you're a little confused hopefully it'll all make sense at the end and as always I go back and explain things uh so they do make sense oh I'm sorry this needs to be an optional because I don't want to give it a value because nothing is focused in the beginning they gotta actually tap something to be focused so that will be an optional and another reason because when we

make it nil that will dismiss the keyboard again you'll see that in play later so let's use this enum so on each text field right we have first name text field last name text field email so on each one I can set like what their focused means so I can do dot focused and you can see I get this

uh parameter that has equals in it where I can like give it a value so Focus uh see it takes a binding to a focused state which our Focus state is up here on line 13. so I need a binding to add Focus text field so if I do dollar sign focused text field there's my binding and then equals is

whichever enum case I have here so I want this to equal and it's got to be hashable which our idioms are hashable by default so this is going to be first name so basically what I'm saying is when this text field is focused the focused text field equals DOT first name it's essentially what that says cool so I'm going to copy this modifier because we have to tell our other text Fields like

hey when you're focused what is it what does it mean is essentially what I'm saying so dot focus focus text field Focus text field accept our last name text field I'm going to put some space in between to make it easier to see so our last name text field uh the focus equals dot last name and the reason we're doing this uh just to get a little bit ahead of myself is because we need to

change the focus manually when the user hits the next button and this is how we know what to focus next so now email focused equals email okay so now that our text Fields know what they're focused when we hit on submit we need to change that Focus now what is on submit okay let me run the app and I'll show you what I'm talking about here maybe should have done this in the beginning to

explain it but this should clear things up so when I have the keyboard open and if on your simulator your keyboard doesn't show up do a command k so see this return button in the lower right this is what happens when on submit fires off what I want to do is one I want to change this instead

of saying return I want it to say next we'll get to that in a second but on submit is what fires off when this happens so what I want to happen on on submit is it to just go to the next text field again we're approving the user experience of using our form so I don't have to keep tapping each one

to hit next they go to the next text field right now when they hit return the keyboard dismisses they have to type in last name and the keyboard goes up and down so you're going to see it's going to be a much smoother user experience so we'll stop that so back to on submit so focused I'm

going to do on submit so now what I want to do is change the focused text field right so I want the focus text field after first name to be last name right we want to go down the form so Focus text field equals dot last name right I want it to be this next one and I'm going to make this

one line again code style you do you if you don't like that that's fine but I'm going to copy this line because when we tap on submit on last name name I want that to go to email right the next one on the list now the interesting thing email is the last one on the list so what do I want to

happen on the last name well if they hit next I want the keyboard to dismiss because again if we look at our form go to account right they go first name last name email and then now they're on the birthday there's no thing so if they hit return here I actually wanted to dismiss the keyboard well all right I already got some code in there messing with it

um I wanted to dismiss the keyboard there so that's why I want Focus text field to be equal to nil and that will dismiss the keyboard when they're done okay so now you saw that was that return button down there well I can change that label so that's just called the submit label so dot submit label and do dot you can see you get you can't like set it to anything so you have to

be returned continue done go join you've probably seen these in keyboards a lot next route search so you would name this whatever is most relevant to what you're doing so on first name I want this to be next and then on last name I also want that to be next right and then email is a little different right because that's when we get to the end of the form instead of next because there is no

text field for them to go to I want this to just say dot continue right continue with the form so now uh when I do this we should have this basic functionality working right so account so look I'm in the Sean uh I'm sorry the first name text field look my button says next when I tap next the

keyboard doesn't go away I don't tap the last name I go right into last name cool then I hit next go right into email and then I see my button change to continue because there's no other like text field to go to there is no next text field so when I hit continue it just dismisses and I can go to

birthday and all that stuff so again a much better user experience now we need to add one little thing to our user experience to really make it nice and that is dismissing the keyboard because right now when I'm in first name like there's how do I I can't dismiss the keyboard I used to hit return to dismiss the keyboard now it's like wait like how do I dismiss it I got to go

next next continue so we want to add an accessory view on top of our keyboard to dismiss it manually should they do that and again all we're doing here is just improving the user experience of our form so we'll stop running this now we want to do this for our entire form like anytime a keyboard pops up on our form which is only in these first three text fields we want to have this accessory view

it's a toolbar that you can put on the keyboard so so here in our form here so I want to make sure I have the I'll do some code folding I need to get better at doing this okay so here's my form modifiers So Below the navigation title I want to do a DOT tool bar and then now I'm going to unfold

this I always like to just fold it to make sure I'm on the right curly brace but now that I know I'm there let's update our toolbar we'll need a tool bar item group and then you see that takes an initializer of placement and placement is the key new feature here again this is new in iOS 15.

so the placement I'll do dot well I'm not going to give me the autocomplete there you go Bottom bar there's a whole bunch of different places you can put it right depending on how you want to use it we want to put it on our keyboard so this will put a toolbar that's always on top of our keyboard right so that's what that is and then the content is a simple button so we'll

do button and then I don't want to like style this or anything like that I guess you probably could I haven't experimented with that maybe you can experiment with that but I just want a basic title In Action right so the title I want is dismiss and then the action is I want to dismiss the keyboard do you remember how we dismissed the key board back up to our Focus State all we do is

set our Focus date to no right just like we did on the on submit for email and that will dismiss the keyboard so that is just focus text field not focus date equals nil and again like I said I'm going to put this on one line I just like the way that looks better so now you're going to see

a toolbar on top of our keyboard anytime it pops up when we tap the dismiss button we're going to set the focus text field to nil which dismisses the keyboard okay test it out back to our account okay so Sean pops up there's our dismiss button so I can type I can go to next but let's say I don't

want to go to next I just want to dismiss boom keyboard dismisses I'm an email dismiss I mean last name dismiss and again I can go through the form just by hitting next down here in the lower right next next then we'll get to email continue dismiss again we just made our form less annoying to deal with and I'm sure many of you have filled out very annoying forms before in the past so

anything you can do to make this user experience a little more pleasant by making it convenient and easy to fly through a form you definitely want to do that and hopefully you learned a little bit on how to do that with the new and iOS 15s things like on submit submit label the keyboard accessory view all that stuff in this video we're going to dive into the new concurrency

system introduced in Swift 5.5 and iOS 15. and I'm going to be honest with you is a pretty big system like there's no way you're going to learn everything you need to possibly know about this new system in this update section like it's it's so big it's going to be released over multiple Swift versions over multiple years like this could be an entire course in and of itself now

I don't want to scare you because in this video we're going to cover the basics and the context and the initial Foundation right the fundamentals of it so when you do go to learn all the future stuff around it you're coming at it with a solid foundation that will help that learning even more so what we're going to do here is again I'm going to give you the context on what it is

why it's happening the benefits of it and then we're going to refactor our Network calls in the appetizer app to the new async await so you have experience with it you've seen it in action and I think that will really help again your future learning so on to what this is why it's happening Etc so here is a gist off from Chris slider highly recommend checking it out if you're interested in

this stuff but you see the Swift concurrency Manifesto by the way if you're not familiar with who Chris lattner is he's no longer at Apple but he was at Apple in a big part of the creation of Swift itself but anyway this concurrency Manifesto here's the table of contents I'll scroll real quick you can see it's ridiculously long tons of code samples all that stuff all the

reasons by behind like why they wanted to do this and how here's the table of contents that I wanted to show you right part one async await part two actors part three four or five so with swift 5.5 and iOS 15 I believe we got Parts one and two and three four and five will come you know in future Swift versions but the foundation is being laid and again check out this Manifesto

if you really want to get nerdy about this stuff right it talks about the past and and why they did things and where they want to go speaking of where they want to go here's the road map and again for context like they've been talking about this for a while but you see the date of this is October of

20 so about a year ago we laid out the road map and now it's starting to execute but if you're curious about the timeline you can see here right you can see the introduction of these new features will span multiple Swift releases features will be introduced in broadly two phases right so Swift 5.5 was the first phase so the first fave introduces the async syntax which we're going to

talk about actor types which we're going to talk about the second phase uh will enforce full actor isolation eliminate data races you know do a bunch more stuff so the reason I'm pointing this out to you is again so you can go check it out you can see their ideas you can see again the motivation behind this if you want to learn all the history but again I wanted to illustrate that it's a huge

topic and we're just going to barely scratch the surface here in this video and lastly like I mentioned uh wwc 21 this was all introduced in June of 2021 right just a couple months ago and it just came out of beta like a week ago as of you know late September 2021 but you can see here's the wwc session I think there's like five sessions dedicated to this topic here's

why I would start by the way meet async await and Swift oh I didn't mean to click on it but that's where I would start but you can see all all these wwc videos so yeah it's a it's a big deal and like I said I think this video will give you the foundation the general knowledge so when you

do watch these videos or do more research again you're coming at it from a place of context okay enough rambling about the history let's actually dive into some code so here I am in our network manager we're going to focus on this call right this get appetizers call which pulls up this list of appetizers that you see here we're not going to mess with our download image function because iOS

15 uh in Swift ui3 or that's what we're calling it I guess also introduce something called async image which wraps up this downloading images like into an object pretty cool stuff there are some pros and cons to it which we'll talk about in the next video but that's why we're not going to mess with this function because that's going to be handled there so we're really focusing on

this get appetizers function what I'm going to do is copy this whole function and the only reason I'm doing this oh let me comment it out is so you can see like the before and after right you can go back for your learning and compare and contrast like what we had versus what we did I think it's helpful to leave the old code there so you can see that rather than deleting it but now

that we have our copy I'm going to start hacking away at this and throughout the process I'll talk about like the benefits of this new async weight system and then at the end I'll go back and do the run through as I usually do so if you don't quite get it the first time through you'll get another

chance at it so one of the big errors that happens in this asynchronous code the old way this old you know closure way or a completion Handler way was you'll notice every time there's an exit from this function like we get an error or we get an invalid response we have to manually call completed right completed failure invalid URL if we miss a spot like let's pretend you know we didn't have this

code here and we just had return well if this happens the code is going to return we're not going to show an error nothing's going to happen it's like a mystery to the user what went wrong as developers we have to make sure we handle every single exit and that's error prone right sometimes people miss one and they forget or whatever and that leads to errors so a big part of this new

async weight is not allowing that so to do that we get rid of this whole completion Handler Paradigm like all together but before I delete this code let's pay attention right what does this return like the end results with this function returns an array of appetizer so let's remember that so we're going to delete our whole completion Handler right and we're going to return that array of appetizer

now that's a much simpler function signature but we're not quite done yet we have to mark this async to use the new async await system and that's one part of it but we also want to throw various errors right we still want to handle invalid URL invalid response invalid data and actually on that note what I'm going to do is we're going to do this first without handling individual errors

because handling these individual errors actually adds a bit of extra complexity that I think might be confusing in the beginning so we'll do a really stripped down version where we don't care about specific errors we still want to throw an error if something goes wrong but it'll be a more general error like you know you've probably seen them before right something went wrong with your task

uh please check your internet connection or try again later right those generic errors we're going to work with it in that format first because that will focus on async await because again handling individual errors adds a bit of complexity that I don't want to confuse you with we still want this to be async throws so the throws means we want to throw an error if something goes wrong

we'll come back to this more when we handle the individual errors but you'll see this is also kind of a catch-all like this won't let us not throw an error by marking it throws oh actually I put these in the wrong spots that's what this error right here says async may only occur before the arrow sometimes you know when you're talking and teaching you mess up little things like that

yeah so async throws goes before this so let's read this function signature right get appetizers it's an async function it's going to throw an error and it returns an array of appetizers you'll notice this isn't optional like we don't return an error if this function is not able to return this it's going to throw an error you'll see I'm just going to comment this out for now

these specific errors because again we're going to come back to these specific errors but uh so I don't want to like have to retype them but for now we're going to keep it simple with just a generic error so the first big thing here is we have this let task URL session data task with URL and if you remember from the previous way like it returned data response error and these were all

optionals right that's why we did if let error equals Air Guard let response equals response guard let data equals data because we had to find out if we had a value here because they were optional well as you'll notice we no longer deal with optionals in this new thing another nice little perk here so we don't have to do a task here what we do is let's and we do a tuple of data

comma response and I'll show you how I know this here in a second try a weight these are the two keywords you need and now we do the URL session Dot shared.data from now this is the new one you can see it's marked async and it throws that's the key thing so it's data from is what we want

now delegate we don't need that that can go away now we do need the URL and that's not an optional right so I I know I said we're not going to handle specific errors here's a little taste of how you handle specific errors we'll just do just this one because I need that URL and I don't want to write

a bunch of hacky code just to get around it so basically garlic URL equals uh the appetizer URL else we don't want this completed anymore right or the return because our return is going to be throw this is the old completion Handler way now when we want to throw an error we will say throw and then we can do AP air which is our custom error that we created before dot invalid URL so that is throwing

our Uh custom air remember that's what I said I didn't want to get into too much but uh you know it'll make it a lot easier so we need the URL here that we unwrapped right there and if that URL is invalid we throw the AP error okay that'll be the last customary we do initially so let's talk about

this line here right this line basically replaces this and if I click into uh data I'm sorry hold option and click on it hit open in developer documentation you can see here's the data from async throws and URL session delegate equals nil as the default that's why I was able to delete it but look what it returns it returns a tuple of a data and URL response okay so that's where I

got this data response Tuple right there now the thing you'll notice if I go back to that it wasn't optional look data and response are not optional which is a huge difference from how it was here where data response and error were optional right now what's going to happen is if they do return nil like we don't have a data or response that's why this throws this will then throw this overall

error that we talked about so we don't need to handle the specific cases when data response or error or nil we just get data in a response and we can use that so that being said I can delete this URL session data task and what I'm going to do is I'm just going to start deleting stuff as we go through and again if you're not quite following I will do a recap to tie it all

together but because we don't even have an error here we don't have to like unwrap bit cool guard that response equals response like remember we're going to handle generic the only reason we wanted to mess with this response is so we could show a specific failure now big picture uh usually you want to be very specific with your users on what airs to show I'm sure you've all received

that generic error that tells you nothing is more frustrating than helpful so definitely want to do that that's why we'll come back and I'll show you how to do that but for now on this easy one I'm not even going to mess with well I'm going to delete the return and completed because that's the old completion Handler way but I'm going to comment this out for now we'll revisit it when we

want specific errors and then this whole garlic data remember data is not an optional anymore so I don't have to unwrap it that goes away so now we're into the do try catch that we're working with our data right where we have our decoder we have our decoded response from the data right and this data is not optional so we have it right here and then I don't need the completion Handler right

don't need that but before I delete it remember the coded response dot request is our array of appetizers just for refresher and if I command click into appetizer response which I misspelled respose uh I won't fix it now because I gotta that'll derail me but you see the request is the array of appetizers this is a refresher so that's what I want to return right because this

function returns an array of appetizers up here so instead of completed I will do return decoded response dot request right because it returns an array of appetizers and then here instead of completed invalid data we'll do throw AP air dot invalid data and then we can delete this

task.resume because we don't have it so now if we go back and look we're doing the same thing but

task.resume because we don't have it so now if we go back and look we're doing the same thing but it's a lot simpler right because we don't have to handle every possible exit so right we make sure we have our URL cool if not throw invalid URL and then we get our data and response back here right and because this is marked try in a weight if it fails it's just going to throw an error right

then we'll handle that accordingly and then we're not worried about specific responses so we can go right into decoding our data just like before and if the decoding fails you know we'll throw invalid data now back to these errors like what we throw kind of like doesn't matter here it's how we handle it on the other side that matters that's why even though I said we're just doing a

generic error I'm throwing specific ones just to basically get xcode to shut up again how we handle it at the call site is what really matters when it come comes to this and I'll show you both ways okay and it looks like I have a copy and paste air here with an extra curly brace that's what happened too much scope so I'm going to highlight this control I to really line that up again and

you know what I am going to delete this just to really clean that up we'll come back to that so yeah one quick run through because I know I felt like I was a little jumbled there so I'm going to really tighten this up here right so I have our function signature of get appetizers it's marked async throws and it returns an appetizer marking it async lets you know that hey you can use the

async and you can see the await keyword here you don't have to Market throws like if you're not going to throw an error you don't have to mark it throws but we do want to throw an error so we marked it throws and then here's where we're unwrapping our URL because we need we need a solid URL right to pass into our URL session here and if we don't have that we're going

to throw invalid URL and then here this is the new way to do a data task and the key difference here is it returns a tuple the data response that aren't optional we don't have to unwrap any more options that's great because if this fails it's just going to throw in error remember like I said it was like the catch-all we don't have to handle all these the individual exits so cool now this is

all basically the same as what we just did right we have our data user decoder we decode it and then we return the decoderresponse dot request in fact what I could do is instead of saying decoder response and decoderresponse.request is that's just kind of a little extra line here I can just return the try and then do dot request at the end of that and that gets rid of that because

this is the response and then dot request so just one little extra line of code because again this is Mark try so if this fails right if I can't decode the data it's going to throw the API or invalid data so as you can see when we're not too concerned about our custom errors really the only custom error we didn't throw is our response one this gets a lot simpler now let's talk about the

call site so if I go to my Advertiser list view you can see where we're calling it here on appear so this is the first order of business right on up here the only thing we're doing in our peer is making a network call so there's a new thing called task which is very similar to onappear and it's basically meant for specifically this thing where you come to a new screen and you're making a

network call the benefit of dot task well real quick before I like forget let's put our view model in here and let's delete on up here is that it'll put you in an async context which means you can use your async await code and what happens is if the user navigates away from the screen before our Network call completes it automatically cancels the network call again this was basically

tailor-made for making a network call when the view loads like we're using it for so now we want to go into our view model to the get appetizers here so appetizer view model get appetizers right here's this function and again the reason this looks so complex is because we're handling the individual errors that's what adds that extra layer of complexity but I'm going to do the same

thing well you see we're getting errors because we messed up our function here I'm going to do the same thing where I copy comment and then paste it down here again so you can see the before and after and I'm going to delete everything really delete this whole network manager keep is loading equals true because that's going to happen but now this gets a lot cleaner so let's scroll up

a little bit I know it might be hard to see but the whole point of this network manager right is to in the success case you see we set appetizers or self-doubt appetizers equal to appetizers right which is our published variable appetizers so when that array updates it updates the UI right triggers all that and we're doing all that on the main thread it's another benefit of async

await we'll get to in a second is we don't have to manually put something on the main thread anymore another common error that gets abstracted away into the language backing up real quick that's kind of the point of async await is to take a lot of this error prone code like I mentioned all the exits from the completion Handler that we had to handle and sometimes you miss one here

we're talking about uh you know routing things to the main queue sometimes people forget that that causes a lot of bugs a lot of error prone code is getting like abstracted away into the language it's one of the benefits of doing this and the code is like easier to read and understand that's the whole like point of why this is happening probably should have mentioned that

in the beginning here we are anyway so we want to return an array of appetizers that's the main goal so what I do is do and it's going to be in a do try catch block because like I said when this fails we want to handle the air accordingly so I'll say APPA tizers equals try await and here's where we use our Network call so network manager dot shared dot get appetizers now what's going

to happen here is if we get a great appetizer everything goes smoothly cool it's going to be set to this and our UI will update if this fails however it's going to go into the catch block I'll handle that error in a second and this is where we will show our errors we'll say alert item equals we don't have a generic error right so if we go to our alerts in the alert thing right all this

alert context we don't really have a generic one we can create one real quick but this video is already pretty long so you can imagine just creating another one of these like generic errors that says something along the lines of like we were unable to complete your request at this time please check your internet connection or try again later some generic thing is what we would

out here to show but again I want to keep this focused on async await and not get distracted with this little stuff here so we're just going to say equals alert context dot I will say invalid response you know again this would be where our generic error goes but that's what we'll put there for now so now what you're seeing here is async call in a function that does not support

concurrency right so this is where we need to mark this as a task like we did before so you do task put it like that and put this in here now you're in an async context there's other ways to do this like you can mark this function async but you got to do other stuff to the function to get that to

work so the simplest way here is to just wrap this in a task to put it in an async context so I want to make sure I handle this is loading switching that back to false on both of these cases so I got to make sure I do that here is loading is true don't make it false that way I hide the

loading spinner whether we get a good response or bad response now that's pretty much it when we're not handling specific errors if I go back up to our main function you see the bulk of the work was handling our specific errors there so again that's what has that confusing complexity that I wanted to stay away from but some things you may notice right this self and you may have seen like weak

self before you no longer have to handle that in the new async await that was another common source of Errors was that whole weak self dance that's out the window and then the other thing you'll notice here on line 21 I'll actually uncomment it to make it easier to see we're manually putting this on the main thread remember I said you no longer have to do that in async await so

let me comment that back out and that's because we now have something called actors so by marking our view model at mainactor basically anything that happens in this view model that's UI related will be rerouted to the main thread so to put it like very simply marking this at main actor uh you know basically does the same things as dispatch queue.maine.async except it again

abstracts it into the language and like does it for you and again for context I'm giving you super high level foundational stuff because again going super deep on it would be an entire course in and of itself but let's make sure this works before I do the uh recap so I'm going to run it and we should see the app acting like like as we expected right nothing should be different

yep here we are our image is loaded app is still working accounts there or they're cool yep cool so again we just refactored the network calls okay so let me do a recap because again I know that might have been fast maybe the first time you heard it might be a little tricky so back to network manager right okay so the only reason we're getting this error is because we didn't

use response so for now I can do that to shut it up do command B should be good okay so now let's run through this again real quick again review repetition that's the key to learning function signature it returns a range of appetizers but we marked it async so we can use we're in the async context we can use async await it throws because we want to throw an error so because we

marked it throws if I go back to the call site in the view model that's why we have to use a do try catch because it throws an error so in the catch is where we catch the thing that's thrown right we catch the errors and handle them accordingly and how we're handling them is setting our alert item to our our placeholder for a generic response that will show uh the alert back to the network manager

okay so that's the function signature that's why we mark it throws and again the benefit of marking it throws here is that's the catch-all if anything in here like fails like we have to handle the error whereas before we could like forget to handle one of the completion Handler exits and we wouldn't handle the error it'd be confusing very common error so here we're just unwrapping our URL

to make sure we have a good one to pass into our our data here now this is the new and Swift 5.5 this URL session share.data from URL like I said it returns a tuple of a data in response these are not optional right you're gonna have them because if something fails and you don't have them because this is marked try now it's going to throw an error and then back to our appetizer

listview model because it threw an error when it tried it it's going to go into the catch block and we're handling that with our generic error okay so that's that line and because we're not like parsing through the individual responses with the status code like status code 200 404 500 like we're not worried about showing individual errors we don't need to do anything with the response we

only care about the data so now that we have the data we can do what we did before which was have our decoder and then try to decode an appetizer response from that data and then I want that response.request which I showed you the request is the array so I'm returning that array up here and

response.request which I showed you the request is the array so I'm returning that array up here and then if this fails for some reason like I can't parse out that array of appetizers from that data we throw AP error invalid data and then now let's start talking about these custom errors right so when I'm throwing this invalid URL throwing invalid data this all happens in the catch block

so you'll notice this doesn't throw one of our specific errors this throws like a typical Swift error so how we can handle the difference here and handle the individual errors is to go to our call site and I'm just going to leave the response one I mean once you see how I handle these two you can see how to do the response one you should be able to put that together we'll do appetizer list

view model here so in our catch block we have to check for the type of error so what we can do here and this is what I was talking about how this adds some like complexity that doesn't really have much to do with async weight the the core principles of it so I wanted to add this at

the end so I wasn't confu too confusing so what we can do is just check for the type right our errors that we're throwing our custom errors are AP errors and as a refresher if I command click into that remember this is the air we created right here that's our kind of custom air type so I want to differentiate between that custom air type and the air that's thrown from here you

know by Swift automatically so back to appetizer list view model right I can check for that if let we'll say AP error equals error so this error is what gets passed to the the catch block and then I want to cast it right as AP error so essentially what this line is saying is if the error that is

in this catch block is of type AP error okay cool let's let's do some stuff here and that stuff I'll do is I will basically do similar to what we did up here right where we switched off the air and checked the cases right so I will switch AP error and then you see I hit return another new xcode 13

benefit it gave me all the possible cases right so essentially I want to do basically this same exact thing right here right so just to really play it out we'll say alert item equals alert context.invalid URL I'm just going to copy and paste this so I can speed this up a little bit

context.invalid URL I'm just going to copy and paste this so I can speed this up a little bit and this is dot invalid response invalid data and then unable to complete now you'll notice if I go back to network manager I'm only possibly throwing invalid URL and invalid data but I want to keep

these other cases in case that ever changes in the future but really invalidate an invalid URL the only ones that are possibly thrown but this is how you you check for your custom error right is it of type APR and if it's not of type AP error then you would do an else statement on on that uh if let up

here right if that's not the case then we want to set our alert item to our generic error and I know this is invalid response but remember this is just the the generic error placeholder so you can see why I didn't want to like start with this because this is just handling specific errors doesn't really have much to do with async await so I don't want to confuse you with that hopefully that

wasn't too confusing feel free to ask questions in the comments or on the slack Channel but that is async await again if you're not handling specific errors it's really short simple nice and again the main reason you may think oh this isn't much less lines of code it's not necessarily about being less lines of code even though sometimes it is it's more about like I said back to the

network manager and all these completion Handler exits it's more about abstracting away many of the common errors when writing asynchronous code again handling all the exits doing the weak self dance routing things to the main thread those are all very common errors and what async away does is abstracts that away into the language and protects us developers from making those errors

now let's talk about async image a wonderful addition to Swift UI and the use case for it is like our appetizers right we are downloading an image for our cell here well to refresh your memory here I am in the appetizer list cell and we wrote this appetizer remote image remember that if I uh command click on it we can go to the definition here jump to that and you see we

had this whole like image loader remote image appetized room and image it was kind of this confusing like dance we had to do to get this working well all this gets handled I shouldn't say all of this because there are some pros and cons we'll talk about it at the end but most of this gets handled in async image for us again real great stuff so back to appetizer list cell

here I'm going to comment out appetizer remote image that's what we had initially and now I'm going to Type async image right you see it right there and if I do the initializer you see we get a couple different ones here so we have just a URL we have URL content URL content and placeholder so the content allows us to tweak the image like we want right we want it to fit in our cell we want

the corner radius on our image Etc and then this one allows us to put a placeholder which is also what we want because that's what we were using before so the URL I can pass in is the appetizer image URL and the nice thing you'll notice this isn't optional because what's going to happen is if this URL Fails Like if the op the URL returns nil it's just going to show the placeholder that's

already all built in so we don't have to like worry about unwrapping all optionals I can't even remember for appetizer.imageurl isn't optional I guess we'll see appetizer dot image URL no that was not an optional but hey it doesn't matter so the content this is what happens as you can see when we get back an image so if it downloads it and everything's great like we got a good image

we need to show an image here if not we show our placeholder so this is the UI image so we can just do image right there and then below it right we do dot resizable remember this was abstracted away I believe in our appetizer remote image here yes we did image dot resizable right so we abstracted that away but we're actually going to do that here now because we're not using our

abstraction anymore and then we'll just do the rest of our modifiers that we had up here right we had dot aspect ratio so I guess I just did content mode there dot fit dot frame of 120 by 90. we don't need an alignment and then Corner radius uh of eight cool now we need to basically

90. we don't need an alignment and then Corner radius uh of eight cool now we need to basically do the same thing for our placeholder except our placeholder is image and we want name not system name you could use an SF symbol like if you wanted if but we have our custom like placeholder remember so we want image named where is that at I guess it's right here we don't uh need that but I

can delete the bundle here initializer so many of them in Swift UI but what is the placeholder image name we had I'm going to go back to our assets here food placeholder right there it is so I'm going to click on that copy that go back to our appetizer list cell paste that in there and then now I need to give it these same modifiers if I want it to look the same maybe there's a case

where you want your placeholder to be of different dimensions different sizes than your actual image you know I'm sure that's the case that's why you have this flexibility but for us it is exactly the same now I'm not going to do this in the video let me do a command B real quick I hate seeing errors

okay what is going on oh that's what's going on uh this takes a URL I pass it in a string so if I command click on image URL jump to definition you can see our image URL is a string but async image takes in an actual URL so let me delete this and we need a URL you can initialize the URL from a

string and the string will pass in is appetizer dot image URL do a command B now normally this returns an optional and we either have to give it a default value or Force unwrap it but like I said a little bit ago async image takes in an optional URL so if this URL fails it's just going to show the placeholder so that's super nice all right command B no errors okay cool good to go so

let me run through this one more time right async image is built in it's going to try to download the image from the URL that we pass in if that image fails or while it's downloading it's going to show the placeholder which we set here once the download is complete and is successful with an image it's going to show the image and then we added our modifiers which again are the same

now uh let's actually resume the preview we should see our placeholder here I believe yep there's our placeholder what I'm not going to do in this video but we did in a previous video so if you want to take that on as a challenge go ahead as you can see maybe we have this as a custom modifier right we refactor these away so instead of adding the same modifiers to both things we say maybe this

is a list cell image style or something like that right but feel free to take that as a challenge if you're not sure what I'm talking about I believe we did this a couple videos ago where we refactored our AP button to use the standard like button style now let's run this to make sure it works and then I'll talk about the con to using this method versus the method we were

using yep there you go you saw the uh placeholders for a second while they were loading and then here they are right here's our all of our image now the downside to async image is that you'll notice in our remote image well I guess that will be in our network manager right where we did this where we downloaded the image we have a cache right we're caching the images and if we know we have

that image in the cache we're not downloading it again right we already have that image well the bad thing about async image is it doesn't cache for you so if caching is important to you I wouldn't use async image I would use our old method that we did before now let me expand on that if caching is important to you so for our app right let me pull it back up right we

have like five images you can't really scroll that far I would say maybe we're borderline um but you know if you had a list of a thousand things and as you were scrolling every time like nothing was caching absolutely you want caching I think we're kind of on the limit to where like caching's not a big deal because we don't have that many items like there's not that many being

redownloaded but again this is very situational on your product if you're downloading a bunch of stuff and it's insanely inefficient absolutely absolutely cash it you know if you only have a couple and maybe you're not like re-downloading much maybe it's not that big of a deal again pros and cons that you got away for your own project your own product your own team that kind of stuff

but I did want to point out that is the downside of using async image even though it's super simple right and we didn't have to write all this kind of convoluted right we have there an image loader a remote image an appetizer remote image kind of convoluted that all gets abstracted away into just this and then again once we abstract away our modifiers like this is really simple you know just

a couple lines of code but again the downside it doesn't cache so that's how you use it use it accordingly in your future projects now that you know the pros and cons and how to do it in this video we're going to run the appetizers app on iOS 16 to make sure everything's all good and then we're going to talk about some new Swift 5.7 features things with the flet and the guardlet as

well as new regular expression syntax introduced in Swift 5.7 to help us with our email validation so first things first we're going to run the app on iOS 16. so I have the iPhone 14 pro selected because that'll give us iOS 16. I think all the simulators will give you iOS 16 actually so yeah we just want to run through the app make sure everything is working as expected so home account

order everything looks good so black and shrimp there it is add to order cool there's our order avocado spring roll things looking good dismiss it chicken dumplings add to order cool now we have two in our order so when I click on my order there's the two place order in our print we print out order place like that's all we're doing again demo app and we can swipe to delete there we're

good one order okay things are working fine we're going to come back to this account when we do our regular Expressions to validate our email we're going to come back to that so let's make sure actually let's make sure things save in iOS 16. so we'll do Sean Allen email is my email at email.com cool extra napkins and frequent refills novel I don't want frequent refills save changes

profile saved hit okay stop rerun what I'm doing is just making sure things are persisting in our user defaults account there we go Sean Allen my email gmail.com cool okay so iOS 16 pretty smooth sailing things are working so now let's talk about the new Swift 5.7 stuff and we'll start with the

if let in the garlet way that we unwrap optionals so what's new in Swift 5.7 is you no longer need the boilerplate like if let error equals error you can just cut that out so what I'm going to do in this project is we'll do search for if let and we see all the places we're using IF let so not many

places this is old commented out code that we don't need because that's our old way of doing things before async await that we did in iOS 15. this is where you wouldn't use this new feature so if let image equals cash dot object whatever you've probably seen this before right we do if let image equals image and then you know you do a bunch of code this is the fix is where you don't

have to do if let image equals image you can just do if let image and it's the same thing so just removes a little bit of boilerplate code but we're going to go through our app and search for all the iflets and the garlets and make the fix fixes but I just want to point out it's not at every

single if let it's only when it's like if let image equals image not if let image equals cash dot object for key whatever so same thing here we don't want to do the error because we are casting the error so that won't work with it so now let's search for the gauntlets that was all the if let's and by the way you'll notice I'm like manually searching and going one by one into our project as

you can imagine if you have a giant ridiculously huge project this probably isn't very feasible to go one by one so I am going to link to an article that will show you how to do a find and replace for the flet and the garlet that will change everything that would make me a little nervous if I had like a huge project with thousands of files and just doing a find and replace everywhere

that would make me nervous um but also the the alternative is to go through one by one so I don't know and you know obviously if you're going through manually one by one you can make a mistake so it's uh It's tricky to go through and fix all these so anyway these are all of our commented out

code here I'm just going to go down the left on the the search thing we're not going mess with the comment to that one again garlic URL equals URL that's fine we don't want to change that down here guard that URL equals URL I'm just going down this lift okay here's one guard let data equals data so here we can just do cardlet data again it's just a very small syntax change but it is nice

quality of life because you see this everywhere guard lit image equals image or UI image equals image nope get rid of that now it's just that so much cleaner again it's a small thing but these small little quality of life things like really add up okay not there regardless user data equals user data nope we can do or just garlit user data through command B and down here okay these

are just regular guard statements so now let's run the app just to make sure we didn't break anything cool that's working this is the only one I was I was a little nervous about this retrieve user because this car that user data is based on this user data in app storage that's optional so let's make sure this works because I believe it'll work account it is retrieving the user it retrieves

Sean because remember this is in the retrieve user function and this is where we're retrieving our existing user for the account and it did retrieve my information well let's stop and rerun just to be sure I can't remember if I rerun I do that sometimes I'll leave the simulator running and it won't run the new code so account yep it did pull in my existing data so that works so again

that if let garlic super nice quality of life thing just removing some unnecessary boilerplate now let's talk about regular expressions in Swift 5.7 so for that we're going to go to our utilities extensions our string extension right because this is this gobbledygoop stuff that we put in there and don't worry if you don't understand regular Expressions uh most people even programmers don't

they usually just find something to copy and paste that is not uncommon and but Swift 5.7 introduces a couple different ways to work with regular expressions of course I'm not going to dive into everything about the introduce because it's pretty involved actually and to be blunt I'm not a regular Expressions Pro I'm one of those people that just like I kind of know what they

are all right cool let me copy and paste but Swift 5.7 now is native support for regular expression so if we do slash and then slash you see me get syntax highlighting and now this is a regular expression it's not a string anymore remember if I I'm gonna do command Z to undo that it was just a string and we're passing that string into a predicate matches now what I'm going to show

you is way more code than this however it's a lot easier to understand and when I was doing this I discovered we have a bug so let me show you the bug we'll rerun the project so when I do my email go to account and you see email.com with our current regex you can do.com.com save changes

profiles saved so we're allowing multiple dots we only want one dot after the at right we don't have.com.com I believe these top level domains cannot have multiple dots someone can correct me

have.com.com I believe these top level domains cannot have multiple dots someone can correct me on that but obviously most of them aren't like.com dot Co dot IO or dot gov like there's just one of them right so that is a bug in this regex but I also noticed something when I did this because here's what Swift will do for you which is awesome or xcode will do I'm sorry it will refactor so

let's get rid of the string I'm just going to get rid of the quotes at the end and replace them with the slash so now we have regex and then now when you highlight it right click refactor convert to regex Builder so one thing that's new is with 5.7 is just native regex will be supported actually you know what I'm gonna do a command Z command Z I'm going to copy and paste and then comment out

that code that way we're preserving the old stuff so what I can do now well first of all let's get rid of the the predicate stuff we're not dealing with and as predicates anymore I can highlight the regex remember it's got to be the native regex you can only do this when it has the Slash and the Slash and it recognizes regex right click refactor convert to regex Builder now you're

going to be like whoa first of all let me fix this equal sign and I got a bunch of Errors let me return something right because our computer property needs a return Boolean so for now we're going to return to I think it's just going to get xcode to stop we're going to return false we're going to like change that because we don't want it to always return false okay we're getting errors

because I didn't update to iOS 16. so because regex does require the iOS 16 stuff so go ahead and do that I mean this is the simpler way to do it by the way like say you did have a project that you didn't want your minimum Target to be iOS 16 well then you would need to do uh let's go

back to the code here then you need to do the you know if at available iOS 16 do all this else you know iOS 15 and Below do all this we're not going to dive into all that but you could support that I just want to focus on showing you the new regex stuff like I said this is a lot more code however

I would argue this is a lot more readable so I can see okay the regex is one or more of a character and you know we're allowing specific characters A to Z 0 to 9 in lowercase A to Z and then the at symbol right is going one by one so cool the first part hey just any character essentially and

then the at symbol and then after the ad symbol again any any character and then this is where I see the bug here I don't want this string I don't know why that was in there again I'm not a regex professional here and then I don't want one of any character I want a specific dot right so you

can pass in a string for if you're looking for a specific string so I want a DOT and then here up to 2 to 64 characters right it's got to be at least two characters Max is 64 of any you know character and then what we want to do is we don't want to return false all the time we want to check

if there's a match so we want to turn self dot whole match of and you can see it returns a regex optional if there's a match it will return it but it'll be optional so the regex we want to pass in it's not email format we'll call this email regex just for good naming so email regex that's what we

want to pass in email regex so what is going to do it's going to see if there's a match if there is a match it's going to return it well I don't care what the match is I just want to know that it exists so I'm going to say return not equal to nil right so we have to return a Boolean so this is

either going to be true or false if it's not nil this is going to return true that means there's an actual match if it is nil that means it's going to return false that means there's no match so is valid email will be true or false based on that now just to repeat like I said this is a lot more

code than just these three lines but look at this gibberish like no one I don't know I guess you can kind of figure out what it means but I feel like this reads a lot more clear for new Developers coming into the code base new people joining the team I like this regex Builder a lot more cleaner maybe you like this other way cool do it that way but just as an example this helped me find

that bug when I when I converted this because I saw that remember we saw this slash slash I was like what is that I don't need that and it allowed me to to clean this up and then use the whole match to find that so now when I go to the iPhone 14 pro let's double check to make sure our

email is good and again I'm going to run through the whole thing since we like did this right so if I type in just my email and I hit save changes invalid email and then my email app well let's get rid of the keyboard command shift K you'll still see that dismissed down there that's because I'm just hiding the keyboard at then now hit save changes invalid email okay we're just going to

start building this at Yahoo save change nope I need the dot dot save changes nope invalid email okay now do com save changes profile save great now let's try what was broken before.com.com

save changes okay that still work because I forgot something so we'll stop running this so again this makes the regex more readable so in my opinion it's easier to find errors like this so what I did was after the at one or more character of class any of I'm saying I can have a dash or a DOT I don't want a DOT I'll allow the dash but I don't want a dot in the domain name I

think dashes are allowed if they're not allowed hey just delete that line but now when I run it now because again what was happening the reason I could dot com.com is because I was saying any of dot or Dash well now I want to clear this up so like I said the regex Builder breaks things out so it's much more readable so now when I run the appetizer app go to account.com

invalid email doesn't work by the way this error up here publishing changes from review updates is not allowed that is an xcode bug if you Google that you'll see a lot of people saying like no it's just it's an xcode bug so don't worry about that but uh yeah so now our regex is working as expected and if I go back to just a regular.com now when I do save changes profile saved so that

is regular expressions in Swift 5.7 one last bonus tip that I noticed as I was you know building this update here I misspelled respose right appetizer response is what it should be you see I had this little red line under it you may not have that that's how I noticed when I was doing this update like oh I misspelled that to do that do edit format spelling and grammar and then check

spelling while typing this will spell check stuff and it pays attention to like the casing so now I know that I misspelled response so I'm going to right click refactor rename that way it renames it everywhere we'll say response right let's actually spell it correctly hit rename good to go and then

I believe there's one more in order yes offsets so it's just there's no e in offsets so that was just a little bonus tip on how you can you know notice any spelling errors and fix your spelling pretty quickly so we focused on a lot of Swift 5.7 stuff because when we ran the app everything was smooth and iOS 16 and there wasn't any Swift UI updates that were pertinent to the way the

appetizers app works so we focused on Swift 5.7 with the regular expressions in the regex Builder that really breaks things out and then the garlic niflet quality of life better syntax this video kicks off the optimization section of the course now what is this section well this is kind of a living section meaning that I'm going to be adding videos to this over time because this is

the chance to go back and revisit the projects that we've done I can you know fix some mistakes because nobody's perfect I make mistakes or maybe I made an oversight or maybe through the conversation in the comments or on the slack Channel I realize there's a better way to build something or architect something right because after you know a thousand or two students take

this there's a lot of discussion and I realize that you know there's some things I probably could have done better so that's what this optimization section is for it's a chance to go back and fix and optimize things and I've done this in a previous course and this turned out to be a lot of people's favorite section because as you'll see through some of these videos is we start to have

nuanced conversations about you know how you style something how you structure something how you architect or build something right so this is more more nuanced than like a straight up tutorial and like I mentioned a lot of this usually comes from discussions with students when they ask questions so back to what I said said about this being a living section you know this is still during

the pre-sale the course isn't even fully done yet you know over the next three to six months a bunch more students are going to take this course more questions are going to pop up so over that time period uh you know if you are one of those early adopters taking this course right as it releases I would check back in a couple weeks couple months because again I expect this section to you know

have a few more videos in it okay so with that out of the way let's jump into a project and start optimizing right the whole reason why we're here so open up your Apple Frameworks project and we're going to do two things here the first thing we're going to do if you see on the framework detail

view is we're going to add a view model right we don't have a view model for this yet and this is going to bring up again an interesting nuanced discussion about should we even add a view model here uh it'll also give us a chance to use at observed object because before we've been using at State objects for all of our view models well you know as you can see we're relying on a framework

so you know we're going to pass that in anyway I'm getting ahead of myself the second thing we're going to do is if you remember this Safari view that we created using the UI view controller representable to show the Safari review controller well again somebody mentioned in the comments and this I completely missed this is that iOS 14 introduced a link object in Swift UI that kind

of renders this obsolete now it's not 100 the same so there could be value in knowing both but we're gonna we're gonna talk about that at that point so anyway those are the two major things we're going to handle let's get to the view model first okay so scrolling up here I'm going to copy all of

this and we're going to put it in the view model and I did copy instead of cut because I don't want xcode to yell at me quite yet not ready for that it's too early in the morning command n for a new file Swift file and then we're gonna do framework detail view model now this initial part should be

you know a lot of review because we've done a lot of view models by now Imports with UI final class framework detail view model and of course what is it gotta conform to observable object now I'm going to paste in the three things I brought over and we're going to adjust this a little bit so this can be a let right we're not we're not tweaking or changing the framework

we're just kind of like reading the data and instead of at State private VAR again this is review we've done this a ton right this needs to be published because again on our viewmodel we want to broadcast whenever that changes and actually as I'm typing this this is actually the thing we're not going to need anymore I'm going to keep it here so you can flip back and forth

between doing it the Safari view controller way and doing it the new you know switching to Safari separately we're going to dive into that when we do the link thing but I'm going to leave that here for now so the main change we got to make is with this binding so when you pass a binding to a view model uh you have to initialize it so as you can see it says class framework detail viewmodel has

no initializers that's because we didn't give this a a value we didn't give our framework a value either so we're gonna have to create an initializer that gives these two things a value however we got to do something different with binding when we create an initializer on our view model we'll talk about that in a second so let's create our initializer and this is just

the typical class initializer so init and then we want to pass in a frame work which is a type framework and then we want to pass in is showing detail View and that is a binding uh Bool so it's a binding bull now I'm going to try something right so I want to do self.framework

equals framework again typical initializer stuff self dot is showing detail view equals is showing detail view now it's going to get an error should right yeah cannot assign value of type binding bull to type Bool so right now it's showing details is a Bool well at binding is just a property wrapper so we can actually write this out the Long Way VAR and make it of type binding

just like we we passed into our parameter down there and then now we should be good to go so essentially binding is kind of a shorthand way to write this but also when you declare it like this you have to use the wrapped value you're going to see that in a little bit but when you use

at binding it kind of does all that for you so this is kind of like the long way to do it but we have to do it here when passing this into the initializer so now our view model is set up let's go back to our detail View and real quick you know I like my view model on top

okay so now I'm going to delete all these because we have them in our view model but actually hold on we have to do at observed object remember this is where we used to do at State object to create our view model VAR view model and then we don't set it equal to something remember it was State object we were setting an equal to the initialization of our view model well we're going

to be passing it in with the observed object so our view model is of type framework detail view model right we're not initializing it with a value because we're going to be passing it in so because we didn't initialize it with a value anytime we create a framework detail view we have to have an initializer on that now that creates a view model at that point and passes it in so I'm

going to do a command B real quick so xcode can tell me all my mistakes in life okay all the way down here so here we just want to do the typical view model dot right because we moved everything to the view model so command C for the viewmodel dot command V and then up here yep uh command V and here's where you're going to start to see some of the wrap the value coming into play

yep so this is showing detail view if we go back to the view model right this is where we declared it not as an at binding because again that would take care of all that for you we literally went the long way and say it's a tight binding bull so here's where you have to use dot wrapped value and you can see the underlying value referenced by The Binding variable right

so again this is just kind of the long way to do it okay one more command B we should be fine on this screen the or no okay yes previews I was going to say we should be fine on this screen the issue is going to be when we initialize a framework detail view because we no longer initialize it with a framework is showing detail yada yada we initialize it with a view model so

let's get some practice with our preview here and and initialize our framework detail view get the autocomplete you see it takes into viewmodel we can do framework detail viewmodel and then we initialize that with a framework and do we have sample framework on here I can't remember mock data dot sample framework yeah it's been a while since we touched this project right okay

and then now uh hit return here for the issue in detail again in our preview remember we can dot constant you know false just to give it a value okay that sets up our preview but that was a preview sorry I know that was bad of what we're going to be doing uh when we initialize our framework detail View and if you remember when do we initialize our framework detail view

well that is in our framework grid view when we actually tap on one of the Frameworks and you can see xcode's yelling at us for where we're messing this up here so we're going to do exactly almost exactly what we just did here so when we initialize this framework detail view we need a view model Right This Is Us creating the view model on the previous screen and injecting it

into our framework detail View and again back to our framework detail view in that scenario where we're we're injecting our view model that's when you use observed object again before we were doing you know equals and then we were initializing our view model that is when you use State object when you're creating a new one on that view okay I think I've said that a bunch before but again

remember my main goal for this course is for you to understand this passing of the data okay so because we are injecting in we're using observed object let's go back and create our view model here so framework and again the reason why we're injecting it is because we're relying on data from the previous screen which is what we're on right we're relying on this viewmodel dot selected

framework and let's hit return here to line these up and then is showing detail view right we're relying on this binding well the view it's on the V model viewmodel that is showing detail View okay my font is like really really big I'll make this small so it's not super ridiculous oh remember because it's a binding we need the dollar sign forgot about that a little smaller

okay command B to make sure nothing is broken okay so we should be all set up with our view model on our framework detail view let me run through that one more time so now when we tap on our framework right we're going to initialize a framework detail view however we're creating a view model here because we're relying on the framework that we tapped in we're relying on the is showing

detail view that's up in our view model right we're relying on data from a previous screen so we use that data from the previous screen create our viewmodel here inject it into our framework detail view so let's go to our framework detail View and because we're injecting it we're using add observed object and we're not initializing a new one we're just making it up type framework

viewmodel and then now you know our view model has that data right we pass the framework we pass the issue in detail view again this is the showings far view is kind of irrelevant at the moment we'll come back to that but we should be all set up and then we just switched everything to view model view model view model so let's make sure this works and then we'll talk about

like the Nuance of you know why you should do this or why you shouldn't do this okay here we are again command shift a to switch to dark mode I just don't like this app in light mode click on AR kit cool there's our AR kit stuff I hit learn more okay the behavior is exactly the same which is expected because all we did was refactor and everything is working so now let's talk about like

should you even do that right because you could argue if I go to my my framework detail view here right you could argue it's just a framework is showing detail and then if we if we continue to use the link like we don't even need this one so really it's only two properties on this so I guess the the debate if you will the Nuance should you even do this right because there's a valid

argument for Sean it was much simpler to just have those two properties here like why are you creating a view model for two properties you're almost adding unnecessary complexity to make it more confusing than it was that's that's argument a right so again it's Nuance the other side of that argument is you know you should be consistent with your coding right if if all your views have

view models you know any new people coming into your code base they're going to expect that right if some of reviews have view models some don't that could be confusing right so you can see how you can see why this type of stuff is is very nuanced and highly debated right this is why there's all kinds of architecture and structure you know debates in programming you can see both

sides of it right so I wouldn't argue with you if you thought the adding the view model for this added unnecessary complexity I wouldn't argue that that's kind of how I feel but at the same time if you want to preach consistency in your code base you know because that makes things understandable I agree with that as well so you see the dilemma here and welcome to the wonderful

world of online programming debates this is why I stay away from this kind of stuff on Twitter because it is it's it's meaningless the what you should do here right for your project your team whatever that is you all should come up with an agreement on the style that you all find is best for your project right there's no blanket correct answer do what's best

for you and your team okay let's talk about link now not Zelda like the like a link so basically we want to replace this button if I run this again real quick let me tell you what we're going to do with some visuals here so tap health kit this button right now as you can see is a button with a label and this button when it's tapped we're flipping is showing Safari review equal to true

that presents this sheet that you see here we've done all that before well again new and iOS 14 which went over my head I completely missed it this is kind of the problem with swift UI being so new and so much getting added it's very hard to keep up with everything even for someone like me who it's kind of my job you know with Swift news creating content it's kind of my job to keep up

and still stuff slips through the crack so if you're not up to date on everything like don't don't worry about it it's tough anyway we're going to basically make this a link that pops open the Safari app it doesn't keep you in the Safari view controller it pulls up Safari app but it is built into Swift UI so we don't need to have here in our UI kit components right this

whole Safari view with make view controller all that stuff whoops did not mean to do that uh this could all be irrelevant right all you would have to do in the framework detail View I'm going to write this above our button because we're going to use it you type in link initialize it you see we want a destination and a label as with all the Swift UI stuff there's a bunch

of different ways to do it the reason we want to label is because that allows us to kind of create our own view if you just did the localized string in a destination URL you're going to get the typical plain blue text link no we want our we want our red button we like the way that looks so destination and label and the destination I'm going to literally copy and paste it from here

right it's the same URL right so what this means is if we have a URL like it doesn't return nil we're going to use it if it does return nil we're going to send them to apple.com as like a default so paste that there because that's the same and then hit return here in the view builder for the label and now this similar to a button right if you think about how the button structured the

first part of the button is what we want it to do the second closure in the button is how it looks similar thing right we want this to go to this URL how it looks is in the view Builder and we're literally going to do the same thing copy paste the AF button into the link and I'm just going to

um comment this out because I I want to keep it in here so you have like a reference for both methods because again there's a slightly little difference that you may need okay so right now we just have our link we don't have our button we can actually even comment out this sheet stuff because we're not even using the sheet right we're going to pop open Safari the app so let's

look at that run it click on metal see our learn more button looks the same right if we didn't do that initializer it would have just been a blue typical link button but now we got our styling that we want tap learn more okay see how it popped us over to Safari it didn't just slide up to Safari view controller we're now outside of our app in Safari right we can navigate wherever

we want you see we do get the back button to our Apple Frameworks app we see we're completely switching apps now here's the debate again nuanced conversation right I've seen debate on Twitter where people think it's a better user experience to completely pop somebody out to Safari right some completely separate versus just showing a safari view controller because the Safari view

controller is kind of like a limited version of safari and you're still contained within your app I guess that would be the the benefit to it is the user never leaves your app whereas you know here they're leaving your app and going into Safari so again nuanced debate right but I did want to show you this if you use link like we did here it's built into Swift UI you don't need our safari

view you know UI view controller representable you don't need all that you don't need to present a sheet and then this is what I was talking about because we're not presenting a sheet on our view model like we would no longer even need this is showing Safari right that's irrelevant now because we're using our link to open up uh the actual app Safari okay so those are the two

things we handled right we added our view model we discussed should you even add a view model that Nuance we talked about observed object because we hadn't used that yet and then we converted uh to link which again was new in iOS 14 away from our button and popping up our safari view controller so that does it for the first optimization video hopefully that gives you a little taste of like

the the type of stuff we talk about and we fix in these videos uh onto the next one in this next optimization video we're gonna do a lot of little Cleanup in between our barcode app and the appetizers app and then we're going to finish off with some date formatting on our date of birth right if you see this account screen so it doesn't show today's date right it'll show

like a date like 20 years ago for for ease of use right because we're all 20 years old right anyway that's the the gist of what we're going to handle here let's start off in our barcode app okay like I said these are going to be small things but looking at our Barcode Scanner view like the main view we actually don't need this Max width Infinity remember we did this so the the scanner

view would would spread across the whole screen well one tricky thing with swift UI is some views will expand to fill all of their available space some will only take up as much space as they need so an example of this is text let me pull up the canvas here to show it so if we look at this not

yet scanned and again the preview I don't know why I'm clicking on it it's not showing the red box around just the text I wish it was that would really visualize this um but I'll put one up on my own of what's actually going on so we're not yet scanned it's only taking up as much space as it

needs you know a little bit more because we have the padding on it as you see here so it's actually you know there's some padding around it but it's not stretching to fill the whole screen however something like a rectangle or or the scanner view that we have here will stretch to fit the whole screen so what I'm trying to say here is we don't need this Max width Infinity because that's kind

of like the default value for it and if you remember the way we can test this here is If instead of scanner view let's do Rec tangle right this is kind of like our debug mode right let's nope no we don't want that preview let's comment out the scanner view right so our rectangle right this is kind of like our default thing well we don't have Max with infinity we don't need that

because by default it's going to stretch out as far as it possibly can so okay that was just one little piece of cleanup that I wanted to show there that it wasn't unnecessary uh use of Max with infinity however if you wanted your text for some reason to stretch all the way to the edge well the text wouldn't stretch but the frame of the text would stretch all the way to the edge

then you would need to put like Max with.infinity on your text so again there's certain views that I think Mark moykins turn I don't know if you coined this term but I've heard him say it where he says like there's push out views and then there's like pull in views I like how he how he framed that um but again we don't need Max with affinity for that and then the last bit of cleanup on

this barcode scanner is in our alert item here remember we this was an error that I had here that I had to go fix we fixed it in a later video but we're just going to come back make these texts instead of a string so I don't have to wrap them in text at the call site but I do have

to wrap them in text here and again the reason you may want to do this is because it's just I don't know I like the call site to be cleaner because the call site to me is where you know uh somebody using the code right another developer coming in is trying to figure out what's going on right and they only dig into like this kind of stuff the stuff that's abstracted away

if they're like really doing a deep dive so I like to make my call sites uh very very clean and easy to read you know for that reason so did the command B definitely going to get two errors here and that is because I can get rid of you see I no longer have to wrap you in text right it can just be much simpler alertitem.title alertitem dot messaging and if you remember

when we originally did the video I was confused why I wasn't working because I just messed up the setup so to command B should be uh away from our errors and again it's just making the call site cleaner and easier to read and understand okay so that's it for our Barcode Scanner view I'm going to close this and magically into our appetizer project I just had it open behind it

okay the first little thing is I misspelled and our utilities extensions right I think I pointed this out in the edit but I never went back and fixed it there's no T in extension so there we go small little thing here uh the other thing on our appetizer detail view I will go ahead and pull out our canvas here because this will show it hit resume so one thing I forgot is I forgot to add

the G label right we have 99 G for grams right so 99 what of carbs 99 what of protein right we want that to be grams so down here in the nutrition info now you could think that you could go in here and add the G afterwards but that's going to add it to all of them right and we don't want 99 grams

of calories so we do want to put that up here uh where we spell this out but that illuminates something wrong with our setup right if we want to have this this G here this label right we're passing in an INT well yeah we could add the G here but that's going to add it to everything like we mentioned we don't want that so we're going to have to change the value to a string

and we don't need our string interpolation down here we can just pass in value right there and everything Remains the Same except now up here we're going to have to do the string interpolation up here so let's make the preview smaller so again we want to pass in a string and we'll do the string interpolation of appetizer dot calories not carbs calories

cool that should be good and then I'm going to copy and paste this just for that setup get rid of that get rid of that except now we want to add a space g after the carbs and space g after the protein and we don't want calories here we want carbs and we don't want calories here we want uh protein you can see our preview I should be updating in real time hit resume

there we go now we have the G after the carbs and the protein so just a slight little uh fix there and you could argue that like carbs and protein it's understood that it's going to be in grams but hey you want to be explicit with your users no confusion okay next up in our loading view this is

another um another iOS 14 thing that kind of uh went over my head didn't realize you can do this and again this was brought up in the comments so thanks for that so let's go to our loading view uh where the hell is that uik components that's right loading view okay so we no longer have to do this activity indicator for uiview representable we can just do a progress view so the progress View

and then the modifiers we want to add we want to give it a style so progress view style of circular something right yep circular progress view style and you can initialize that with a tint which is a color and we want to make that a brand primary right so we just want our spinner to be the green

just like we had before so now to test this let's go to the screen here and in our appetizer list view here instead of I'm just going to put a bang in front of this so if it's not loading we're going to see the spinner so I'm just using that for debugging so we always see the spinner

when we run it and we're still in dark mode more on that in a second let's go back to light mode cool so you see our dark green spinner it is a lot smaller than we had it I don't know maybe you like that small size I'm going to stop this and we are going to go back to our loading view here and then

another modifier on progress review we can do is dot scale effect and we can pass in a scale of just let's say two doubling the size is basically what we're doing here so let's run this again and we should see our spinner uh nice and big yep there we go big spinner in there and you can play with the scale to get the size you want but our spinner is back working another thing you can

do with this progress view is you can initialize this with a title uh title key here you know you can do loading dot dot now run it and you can see you'll see like the label here it's going to be huge because we made it bigger you can like adjust that but I don't know I just like the spinner I'm

a fan of like minimalism white space that loading to me is just clutter I know it's low coating to spinner so anyway just letting you know you can do that so the point of this is now you can use a progress View and the new thing on in iOS 14 is this circular progress view style that will now

give us the spinner and again you can adjust the size of it with the scale effect here so again we no longer need this activity indicator view the UI view representable I'm going to leave it here just for reference but you can now use uh progress view to do that so nice simpler built-in Swift UI way and if you remember when we built this I was like oh this is going to be added soon I can't

believe this isn't in there yet well I'm dumb it was in there okay next let's go to our assets we are going to adjust our color if you go to Brand primary right because okay let's run this real quick iPhone 12 Pro let's go back to dark mode command shift a so okay there's our spinner okay

this is what you got to be careful with this uh debugging stuff right so now I want to get rid of my bang there to make it so it only shows up when it is loading not all the time again that was just for debug purposes so I could see that okay so we're in dark mode now look at our like our the

dark green is kind of hard to see in dark mode right and especially on the account like look at save changes that the text is kind of hard to read I mean it's not impossible to read but it could be better and you can basically make colors for dark mode and light mode like our brand primary so that's what we're going to do here so in our XC assets see if we have any appearance and then

dark appearance click on dark appearance get rid of that here pull up your right pane here in the upper right and you can see show color panel and then just pick a color you like I'm going to go with a more like vibrant green for when it's in dark mode and we can close that out cool so now

you can see in our normal appearance it's going to be the dark green and dark mode it's going to be this you know much brighter green so now let's run it and you can see look at our tab bar it's much brighter go to our account screen you can see it's much much brighter some of you may even

like that look even better well the one thing I didn't do was uh so this is an image and I custom made that image so it had our dark green and you can do what I did with images I'm just realizing this now as I'm recording so I'm not prepared for this my apologies but I can explain it and

you'll get it so if I go to my empty order here same thing right if an appearance is over here on the right if I add any slash dark now I can add a dark appearance just like we added a different color I could go in and customize this image in in like sketch or something and you know instead of

this dark green I can make that my my bright green that I made it and then I can import that image and then drag that down here to dark appearance and now the image will change you know based on whether I'm on dark mode or light mode right so you would see that image but so apologies for

not being prepared for that it just came to me as I'm recording but uh you I think you get the idea but you can see I actually kind of like the way this looks this bright green it's good color combo uh so anyway you can see how we're changing the colors again command shift a to go back to light

mode look we're back to our dark green dark mode back to the light green so that is how you can use you know light and dark appearance in your assets you know to adjust for that okay let's go back to dark mode because I'm really digging the way this looks uh let's pull up our uh date picker right so

April 2020 that's what it well it defaulted to my birthday but you know when we don't have a user in there because remember my user showed up because we saved it in user defaults uh it would show up to November 2020. well I want to like you know I don't want to make my user have to scroll all

the way back to however old they are right that's annoying for the user so let's say we have like we're in a bar right appetizers or a restaurant you got to be 18. so we want the minimum age to be 18 right so that's where we want this to start at so stop this and actually let me open up my

simulator I suggest you do this too um let's get out of this so we'll go home I'm going to delete the appetizers app uh that way it removes my user default so we can go back to having a the default setup there for when a user would actually change their their date here so we want to go to the the

account view here okay so in the account view right we have this date picker well we want to use a different initializer of the day picker because we want to get a date range so I could just add a date range but I found tweaking the parameter sometimes messes it up so how I usually do it just to be safe because I like getting the autocomplete I just do another date picker I mean

I'm going to delete the one on top and then look at all these different initializers this is what I was talking about like I didn't want to like try to create my or try to custom my own and mess it up but here's what we want we want the closed date range that you see here however we also want our date picker components so here here it is displayed components you can barely see the edge

of it but we have our title selection closed date range display components that's the initializer I want right there you can see so the title is going to be the same command C for the birthday cool uh same thing here for the binding and like I said you could just add in this parameter manually I don't know sometimes I found I maybe I messed that up whatever that date I like to do the uh

initializer and and fill these in just to be safe so the thing we're missing here so I can delete this up here now uh the thing we're missing so we have our title our selection our date range which we don't have yet in our displayed components okay so we need a range of dates the date range we want

is we want the we don't want somebody to enter a birth date that's uh younger than 18 years old so that's the the end of our date range also at the beginning of our date range we don't want the user to be able to scroll back to like 1492 because you can do that on the day picker right and you know

you want to limit your users so they don't import crazy dates and mess up your error handling right because you probably didn't think to handle when somebody entered a date an age of like 1492 so anyway we want to give a very close range of dates so we need to create a date that is 18 years ago and and then also one that's let's say the max age is 110 right if somebody older than 110 is

coming to your bar what are they doing they're 110 anyway that's what we're going to choose if you want to adjust the dates you'll see how easy it is so let's create an extension on the Swift date object to create these dates so in Utilities in our extensions folder do command n Swift file hit

next and it's going to be date Plus EXT it's our typical extension format here and then extension date and we're going to create two computed properties right one is going to be VAR 18 years ago and that's going to be a date and here we're going to return just today's date just for

now to get so xcode doesn't yell at us we're just setting up here and another one VAR 100 10 years ago and again that's also going to return a date and he's going to return today's date and I forgot this is new in Swift 5.1 or whatever we only have one line you don't need the return I keep forgetting about that so now let's do some date math if you will

um to figure out 18 years ago so this is going to introduce you to uh some fun with dates doing some date calculations I could do an entire course on date calculations this can get pretty complex I have a bit of experience with it kind of like building calendars and stuff but this is like a simple version what we're going to do is basically subtract 18 years from this date so we want to

do calendar dot current dot date by adding to and there's no like subtracting which is confusing so you have to add a negative number date by adding uh oh I didn't even do the right initializer there there's another parameter so again initialize that date by adding value to right because we want to put a value in there you'll see so the component we want to add right you can do like

you can add an hour a minute a month a nanosecond we want to be in the year range here right because we're subtracting 18 years from this date so the value we want to add is we want to add negative 18 years to today and it's well here too you can you can pass in a specific date like if you wanted to

do 18 years from the year 2000 like you could you know create a date and do that but if you do date like that that is uh today's date so our calendar we just want to show 18 years ago and creating this returns an optional but we're going to go and force unwrap that because this is all like default

stuff you know if you were creating your own date and passing it in then you might want to unwrap your optional but this is all like apple default stuff pretty safe so the same exact thing for uh 100 10 years ago except instead of subtracting 18 years we're going to subtract 110 years okay so let's actually go back to our account view I was about to run it prematurely our date range is we

want to use the extension we just made let's do a command B to make sure we get all the autocomplete stuff so we want to do date so this is the first part of the range dot uh 110 years ago so that gives us that date dot dot and then the end of the range is date dot 18 years ago so let's run it on

the simulator check our date picker and see what we got okay go back to account okay remember we we deleted the app so we have no user and you see it defaults to November 21st 2002. that is 18 years ago today is November 21st 2020 right cool so you cannot enter a birthday younger than 18 years old

let's try it so see it's all grayed out here right I can't pick a date even if I try to go further into the future I can't click it when I do my scroll wheel if I try to go to 2010 nope go back right you're forcing to be at least 18 years of age so click off that and then now let's go back

to I don't know why I clicked off that now let's try to pick a ridiculous date right okay I'm back in the damn it I'm back uh I see I'm back in the 1900s 1800s whatever you can go way far back and you see it automatically Scrolls me to 1910 which is 110 years ago so this is how you kind of block

off the date range and this is the little stuff right you've heard me talk about the first 90 and the second 90 of your project this little like usability stuff is the second 90 you don't have to do this but your users uh you know it's gonna be a better user experience for them rather than as soon as this date opens up it opens up to today's date they gotta scroll back 30 40 years however

old they are like that's annoying well if you kind of you know put it at the minimum you know that at least gets them you know halfway there potentially but really that's just an exercise and kind of like you know making some date calculations and and putting some limits on your calendar if you need to do that right no like we for example this also limits putting a date in the future right

because if you're not born yet what are you doing and again this is nice to do so your users can't put bad data on your database by these ridiculous birth dates anyway small little little stuff like that but that wraps it up for this optimization video again we did a lot of small cleanup fixed that calendar and that's it for now on the optimization but there's certainly more to come

over the next couple short videos we're going to review passing data in Swift UI right State binding and observable object all of that stuff in this review part I think it's very very important like it's part of the learning process right you don't just hear about it once and now you know it right you've heard me talk about it you've heard me explain it we've had a chance to play with it

and actually use it by building the past four apps and now let's review it to like really Hammer at home because remember like I said at the beginning my whole goal for this course was for you to leave it having at least a foundational understanding of how State Works binding understanding the Swift UI mindset how there's one source of Truth you change that source of Truth and then your UI updates

right just understanding that like if you're leaving this course understanding that it was well worth it because yeah we may not have covered like all the animations every single modifier every single UI element all that stuff is easy compared to passing the data like the biggest hurdle in learning Swift UI is learning the data part so hopefully after this review where we really

hammer it home uh that'll be successful all right so let's start off with at State and to do that we're going to go all the way back to our weather app because for the most part we've refactored our our state variables into our view model now they're you know published on an observable object we'll review that later but back in our weather app we're using good old plain State now again

remember all the views in Swift UI are structs right like content view it like that's a struct and structure value types so they don't hold State and remember in Swift UI our structs are constantly like destroyed and recreated destroyed and recreated as we're re-rendering these views well the whole point of state is so that we actually can hold the state of this Boolean

this is night Boolean right because if we weren't holding the state every time we destroyed content View and rebuilt it well it would get initialized as false and we would lose like the state of our UI so by marking this as a state uh property Swift UI manages this data separately for us that way we can destroy and recreate content view all we want we still have the value of State you know stored

elsewhere and also when this property changes because it's marked at state that is going to trigger a view re-rendering let's actually go to the documentation to see how they state it because maybe that'll help you understand it when you hear it a different way so here we are in the documentation right State a property wrapper type that can read and write a value managed by Swift

UI right we're not managing it like Swift UI is doing that for us and here we go Swift UI manages the storage of any property you declare as a state when the state value changes the view invalidates its appearance it says hey I'm no longer valid re recompute right and it recomputes the body so that's what I'm talking about when it triggers a UI update another way to think of it is how the

documentation says it right it invalidates its appearance and recomputes right I'm no longer valid redraw me use the state as a single source of Truth or a given view so back in next code let's see that in action right we have our is night variable as false and if you remember when we tap our change day button we're flipping is Knight the true so let's run this on our preview

and that's what's happening when I tap this button I'm changing is Knight to true I'll review invalidates as the documentation says it says I'm invalid redraw me it redraws except now is night is true it's no longer false because we flip that and then you know our background view changes based on that and then our icon changes based on that so that is state in a nutshell and again it's

because our structs are constantly being destroyed so we need to store these properties elsewhere and Swift UI manages that for us and changing that data updates our view all right now let's move on to binding and for that we're going to go back to our barcode scanner app but first let's check out the documentation on binding okay in here it says a property wrapper type that can read and write a

value owned by a source of Truth so it isn't the source of Truth itself it can just read and write a value owned by a different source of truth right and it says that more here in the overview use a binding to create a two-way connection between a property that stores data and a view that displays and changes the data again they kind of say this in multiple ways here right a binding connects

a property to a source of Truth stored elsewhere that's the key right the source of Truth you know for example in our view model right the source of Truth is stored in our view model The Binding just connects a property to that source of truth right it binds them together or you can think of it as creating a reference to it and let's go back to xcode to actually see that in action so if you

remember on our Barcode Scanner view in our view model let's go to the view model here we have our scanned code and we'll we'll review observable object later but just know the source of Truth the data is stored right scan code is stored on our class uh you know our view model right that's where it's stored so our binding basically creates a connection to this value and that's what we're

doing in our Barcode Scanner view if you look when we create our or just regular scanner view we pass in a binding to scanned code so back over to scanner view right this is where we're using our UI you know view controller representable here is The Binding to scanned code and then you know when our barcode scans it we get that data we change this value right but it is referencing

it is connecting to the value that was in our view model scan code right this is the source of Truth our scanner view this binding this is not the source of Truth itself it is a connection to the source of Truth so you can think of a way if we go back to our Barcode Scanner view right the

kind of the home screen you can think of a binding as a way to you know pass the source of Truth down to multiple child views if necessary right it's a way to communicate between views again you're just binding to the original source of Truth which is in our Barcode Scanner view model okay let's move on to coordinators and by the way I am going kind of fast because this is review you know I've

explained this multiple times we've played with it however if you're still confused you're still not quite sure please please please ask questions in the comments or or hit me up in the slack Channel know please like I said I really want you to leave this course understanding this aspect of things so if you're not quite sure I'm not gonna let you leave until you're sure so get a hold of

me uh all right so on to coordinators yeah if you remember let's go to our scanner view right this is the UI view controller uh representable the coordinators help uh communicate between UI kit and Swift UI and if you remember my diagram UI kit you know gets some information in our case it is getting the the barcode that we scanned through delegates that we set up our scanner view

controller that is doing the scanning is passing the barcode to our coordinator and now back to our code right here you can see our coordinator set up our coordinator is created with a scanner view that again is this scanner view that has the scan code binding on it so in our delegate methods right we did find or did surface error let's just talk about the success case right so in

did find this is our UI view controller or UI kit communicating with our coordinator right so our coordinator gets the barcode and it's like thank you view controller thank you for that barcode now I'm going to tell my scanner view what that barcode is so now the coordinator communicates with our scanner view which is a swift UI view that has a binding to scan code it says thank

you view controller for that barcode hey scanner view here's the barcode The View controller gave me and then now the Swift UI scanner view uh can tell it's it's binding it's source of Truth which again was the view model on the home home screen what that new who barcode is and then the UI can update accordingly so again just to narrow in on coordinators think of it as the middleman

in between UI kit and Swift UI UI kit communicates with the coordinator coordinator communicates with swift UI and if you're still unsure how to like set all this up with the final class coordinator again go back and re-watch that section of the course there's no shame in going back and re-watching certain sections or rebuilding certain apps again repetition is the key you don't

just watch a video once and then you know it no shame in going back and repeating things alright so that wraps up this review video covering State binding and coordinators again if you have questions leave them in the comments or hit me up in slack let's move on to the other stuff in this review video we're going to talk about observable object State object observed object

and environment object sounds like a lot but they're all kind of closely related so we'll get through it pretty quick so let's start with observable object and we're going to start with the example that you see here on the screen as our typical view models that we've been using right by the way we're in the appetizers app so as we've done before right we create a class we

have it conform to an observable object and let's go into the documentation to see what Apple has to say about an observable object okay so as you see in here right is a type of object with a publisher that emits before the object has changed kind of like how I described it right with how I say it broadcasts its changes but let's go a little bit further by default in observable objects

synthesizes an object will change publisher that emits the changed value before any of its at published properties changed right so again like I described you know if you market app published like this name variable here whenever that variable changes or property changes it's going to broadcast its change right I think I've said that a bunch throughout the uh the course but again

repetition is the key here I'm repeating myself a lot on purpose especially in this review section again really want to drive the point home but anyway when this property changes it broadcasts its change so that's observable object in a nutshell right it's only one half of the equation because we got to set up somebody like listening to that change but as far as just the observable

object it broadcasts the change but you have to mark it at published if you're running into a bug and you know you're like oh my UI is not updating what's going on double check to make sure you marked it at published because if you don't Market published it's not going to broadcast it okay back to xcode to uh dig into this further so let's walk through the example right we marked all

of this stuff at published let's go through our array of appetizers just to walk through what's actually happening right so array of appetizers we get from the network right this is our Network call that we created well in the success case we get back an array of appetizers from the network right we decode the Json into our our object so we set uh the appetizers we get back from the network

equal to this array of appetizers up here so now what just happened we went from an empty array to a full array and because we mark it published and it's an observable object that change is going to trigger a broadcast we're going to say hey whoever's listening I got I got appetizers now we updated update your UI and who's listening write our appetizer list view is who's listening

right and this is how we set it up right our our state object view model more on state object in a second but now we have a property view model that is listening for those those changes right so now when I do viewmodel.appetizers right this view will will trigger because that change it'll redraw and now it's going to pull from my list of appetizers to create our list so that's kind

of the flow on how observable objects works and communicates so now let's let's talk about this state object up here and if you remember the key difference I've said it a bunch between at State object and at observed objects and when you should use what is when you're creating an appetizer list view model or you're creating an observable object which our viewmodel is that's when you want to use

State object right and by creating you know we're setting it equal to in these parentheses right that's the initialization you may hear it called instantiating initializing creating all saying the same thing but the reason we want to do that is because when we create it on this view it acts just like a normal State like that's why it's called State object because now our appetizer list

view like owns this view model and just like the state variable I described on our weather app no matter how many times our appetizer list view gets created and destroyed created and destroyed which is what happens when it gets like redrawn we're not going to instantiate a new view model right we're only going to create it once and then Swift UI is going to manage that you know elsewhere

that way we can always reference this same view model no matter how many times our appetizer list view gets created and destroyed let's go to the documentation to basically reiterate what I just said so here in state object right it's a property wrapper type that instantiates an observable object right talk about creating one if I scroll down a bit uh here's the key right Swift UI

creates a new instance of the object only once for each instance of the structure that declares the object so that's basically what I just said back to xcode whereas like no matter how many times appetizer list view gets created and destroyed we only have one view model that way it can persist its state now let's shift to observed object which is what happens when you're not creating it here

you're passing it in from a parent view right the the appetizer list view in this scenario we're actually going to use the Frameworks app right wouldn't own the view model it's going to be relied on it being passed in let's actually switch to the Frameworks app to to show it in real life so here I am in the Frameworks app and this is what we just did in the uh optimization videos

so hopefully this is like fresh review for you but we also didn't like deal with this as much as we did State objects so if you're still not quite sure definitely you know hit me up in the comments hit me up in slack I want you to really understand this stuff it's important so again we use observed object because look we're not initializing it we're just declaring hey we have a view model that

is of type you know framework detail view model we don't give it a value because we're expecting the value to be passed in when we create a framework detail view right it's relying on the data from the parent view for this reason and this is the difference between State object and observed object right State object like I said that view will own that view model here The observed object

like it this framework detail doesn't own this it will destroy this observed object every time this gets created and destroyed it doesn't care about it the reason it can destroy it all the time is because every time a new framework detail view get gets created it's getting passed in a brand new view model right let's go to our framework grid view which is the parent view here right

right whenever we tap on a framework we show the sheet we create a new framework detail view which requires a view Model A framework detail view model again we just implemented this a couple videos ago but what's going on here is I have to pass in a view model and again we're initializing The View model the v-model takes a framework and a binding issue in detail view but again the reason

why our actual framework detail view can just destroy this at will is because every time it gets recreated it's getting injected like with a new you know view model that is created on the previous screen or previous View or parent view called the framework grid View and the reason it gets created up here is because we're relying on data right we need to know what framework to show

when we when we presenting our framework detail view right that's why we pass in the selected framework so that is observed object again back to it the the just I think the key thing to know like you you'll be pretty much safe if you just understand that hey if I'm passing in a view model I need observed object if I'm creating a brand new view model like in our framework

grid view here I need State object if you just remember that rule of thumb uh you'll be pretty good okay now let's talk about environment object but for that we got to go back to our appetizer app because that's where we used it right and the environment object we created was the order right which is it's an observable object this is what I meant by they're all kind of similar

um so our order is just an observable object so that's another key thing to remember right it doesn't have to be a view model right remember an observable object the only thing you need to know about that is that it will broadcast its changes right if you mark it published so in this case we're right we we need our observable object to be accessed from multiple screens right we can we can

add an appetizer from our appetizer list View and then on our order view we need to display you know what's in our order and we can swipe to delete right so multiple views multiple screens need access to this observable object this is different from a view model because our view model is very tightly coupled with a specific view right we don't want everything to have access to

it just that view so that's the difference right environment object we want a lot of things to have access to it that's the whole point so where do we put it into the environment well let's go to our app right the appetizer you know app structure and in our case where we want our entire app to have access to it we inject it into the environment at like the highest root View and again pulling

up this visual right that we used before that is our appetizer tab view right all the other views end up being children or or their Downstream views however you want to look at it from the appetizer tab view so by injecting it into the environment here everything's going to have access to it which in our case that's what we want but remember there are cases where you may not want everything to

have access to it again the example I used was the Apple Settings app where I have to go four screens deep well maybe I want to inject something into the environment like right at the settings root view right not the entire apps review just the settings review that way everything Downstream or all the children of the settings root view will have access to some sort of like you know settings

observable object that they can all access that so coming back to our app object here like a key takeaway with environment object is wherever you inject it matters greatly because of a view that's not part of the view hierarchy where you injected it right it's not one of the children tries to access it your app's going to crash let's review how you access this real quick right okay so back

to our order example where we injected it at the root view at our tab view so everything has access to it so in our appetizer detail view right the view that pops up this is where we need to access because this is where we're adding the uh appetizer so if I scroll up right you do add environment object VAR order now this just means hey I'm going to reach up into the environment and

I'm going to get access to this single source of truth right so this environment object is a single source of Truth for all the child views for it so that's how the appetizer detail view has access to it as well as our order view has access to it because we're writing this ad environment object property wrapper and like I said it has access to the same object it's the single source of Truth

just multiple views can adjust it now that's one scenario where you use environment object another one is if you find yourself passing a binding down multiple views now I think all the examples we use we're just passing a binding down like one view which is fine that's what it's meant for got like one-to-one communication but sometimes you know you'll find yourself like having more child

views more child views and if you find yourself passing a binding down like five views that's a good time to use environment object where at that root view you create an environment object that way you don't have to pass the binding from view a to view B to view CWD you just inject it at view a and then view D you know can automatically access it right you don't got to pass it all

the way down the hierarchy so that is another way to use environment object so that wraps it up for the quick review on passing data again I want to stress quick because we've been over all this before but I did just want to go over it one more time to hammer it home but again I know I've said this before please this is the most important part of the course if you don't quite

understand this you know hit me up in slack leave a comment call me like I want you to understand this I don't want you to leave this course having this be fuzzy at all this is where all the value is okay with my my plea done let's move on to the conclusion videos of the course there's a new and improved way to update your user interface in Swift UI iOS 17 introduces the at observable

macro which is a cleaner more performant way to handle UI updates in Swift UI I'll explain how it works and we'll convert the old way to the new way to help you understand here next code I have a basic example of the existing way to update your UI when your data model changes let's run through this real quick to set the foundation for this new change so here we have a data model right now

it's a user this could be a view model for your specific view maybe it's an order for you know an e-commerce app in Swift UI currently if we want to update our UI when something in the data model changes we conform to observable object we Mark any property we want to change with app published that means when the name property changes because it's marked out published the UI will update and

in turn where we use this user object here in our view down here we mark it at State object or add observed object depending on how you're using it that's a different topic and then anytime this state object of user changes are you UI will update here right user.name user.jobtitle the

only change I'm doing right now for this simple example is incrementing the follower account you can see user.follower account plus equals one so when I hit the add follower button you can see 99 followers 100 100 102 you can see the UI updates because my follower account is changing and again to go back up the stack here that's because it's marked at State object and because the user object

is an observable object and the follower count is marked at publish that is how the UI updates if you've worked with swift UI before this should be very familiar to you but I wanted to walk through that to set the foundation for how the new way works okay so let's update this to the new way we'll talk about syntax first and then I'll tell you what's going on under the hood and why this

is such a great change so the first thing we need to do we need to import observation now you may see people importing Swift data Swift data as a whole Imports observation as well so importing Swift data feels a little heavy-handed if you just want observable stuff just import observation and now our class instead of you know conforming to observable object we delete this and in front

of the class we mark it with a macro at observable now we get some errors because observable requires property of name job title follower account to have an initial value because in order to observe something they need an initial value to know when it changes now I have seen things on Twitter that this requirement might go away for a disclaimer I'm on xcode 15 beta 2. it is June 22nd so wwc was

just a couple weeks ago so this is all very fresh so this may change in a future version of xcode just be aware of that but for now we're going to give our properties an initial value because we marked it at observable so for the name just going to give it an empty string same thing for job title empty string for follower account we'll say zero and then bio and empty string as well

so okay we marked our class at observable that replaced conforming to observable object seems simple enough but what's cool is now we don't need any of these at published so that all goes away everything is being observed because it's marked at observable so that cleans things up a bit again we're just talking about syntax right now I'll dive into what's actually going on so that

handles our data model again this could be a view model for a specific view our simple example is just using a user so when we want to use this observable object here in our view instead of marking it at State object we just have it a VAR and I'll highlight this do a control I to line it up but this eliminates the whole state object observed object when do you use which one what

are the rules there the concept of State object and observed object don't exist in this new at observable world now of course you still can use the old code so I don't want to say those two things don't exist overall but if you're adopting ad observable it simplifies things you don't have to worry about State object or observed object it knows here on line 27 this user is marked

at observable so it knows that it is observing these properties for changes to update the UI when necessary so again just talking about syntax we got rid of all the at published we just marked it at observable and we can get rid of State object and observed object so syntactically that is much cleaner but there's a lot more benefit going on than just cleaner easier to read code because the

key thing observable does is Swift UI under the hood is tracking the views that access properties of an observable class let me break that down a little bit so the properties of my observable class are name job title follower account bio when I had them all marked at published anytime one of those underlying pieces of data like the follower account or the job title would change it

would trigger UI updates so a big picture of what observable is helping with it's going to eliminate a lot of unnecessary UI updates therefore improving performance to put a super big picture when you use ad observable Swift UI is doing a lot of tracking under the hood as to which views are accessing specific properties on objects marked observable it can be a lot more surgical with its

UI updates so that's why you're going to see your performance boost and that's why this is such a big update and to add to that example right we're just using the name the job title in the follower account you can see I'm not even using the bio so you may be saying that like oh yeah then only your follower account should have been marked out published that's all that's changing well

that may be true on this singular simple example view but you can imagine in an app something like a user that's going to be accessed in multiple views now this kind of looks like a user profile so maybe there's a separate screen where the user profile is being updated so now you do need these to be marked at published so this just reiterates that when you use ad observable and you you let

Swift UI handle all that tracking of which UI is actually accessing the properties under the hood it eliminates all those unnecessary UI updates and like I said it allows Swift UI to be more accurate and surgical with what specifically needs updated which leads to better performance another cool thing about this observable macro or just macros in general does seem like magic right I

talked about all the stuff that's going on under the hood well with macros basically what they do is they abstract away boilerplate repetitive code into a macro so you can't see it but in xcode 15 if you right click expand macro you can see the quote unquote magic going on under the hood so you can see each property is marked at observation tracked that is how like I said we're

tracking which UI is accessing each property and you can see all this boilerplate code to be honest with you the heavy use of generics if you don't understand all of this that is fine again this magic is abstracted away behind the macro but again it's not a black box that you can't see if you are having an issue and you want to see what's going on with the macro just right click

it you can expand it so you can actually see the magic of what's going on so I think that's great about macros you click hide macro expansion there you go back to observable so to put it simply you get cleaner syntax and better performance this is a great update overall to Swift UI don't be afraid to go back and redo things review videos right like I've said a bunch of times you

don't just watch one video and you get it like repetition is the key like Swift UI is not easy to learn like it took me a long time so if you're still shaky on some things like don't feel bad go back and re-watch the parts you're you're not quite getting and also if you skip the challenges which I know a lot of you did uh go back and redo those now now that you feel like you've

got a little more experience under your belt or take these four apps that we've built right you got a nice base start building and expanding on those apps like start using your your imagination to build a product like right like what feature could make this product better or what animation could could spice this up a little bit to be really really nice that is where like the real

learning comes right like listening to what I say typing what I type yeah that's cool you're gonna you're gonna get your start that way and and you need that for sure but the real learning comes when you have your own idea and you're like okay how do I make that happen and then you figure it out like through other tutorials uh reading documentation experimentation right that's where

the magic happens so again go back and use these four apps as a basis for that I mean just some ideas right you can explore with like landscape mode like how would you adjust the UI to support landscape maybe you want to support iPad right or again maybe you want to add some cool animations and start going down that path on how you can spice these up the next thing I want to talk

about before you go is Swift ui's Evolution we're still so early it's not even two years since it's been announced right it's been a year and a half since it's been announced crazy right and it's still growing it's still evolving it's still maturing like I mentioned in the beginning like best practices are still being established like you know with UI kit you know we've had years and

years and years of high level huge production apps to kind of build these best practices and thoughts none of that exists with swift UI yet so this is me saying use what we learned here as a foundation to help you grow and evolve like I guarantee you in two years and now that I've been writing Swift UI for even longer and longer and longer my style is probably going to change uh you know some of

the things I taught here I'd be like oh man I'm I would have taught that differently and expect that and that's a very big takeaway too is the only thing I can promise you about Swift UI is that it is going to change a lot over the next couple years so just be prepared for that expect that and

the last thing before we wrap up this video is I would love to hear your feedback if I'm being completely transparent and honest like I was a little nervous about doing this course right my UI kit courses I've had I've done my whole career in UI kit I felt confident about that but Swift UI is so new like nobody has a ton of experience in Swift UI because it's only been out for like

a year year and a half so I would love to hear feedback again I have plans for future courses I'm always trying to make them better so good or bad right I can take it give me the constructive criticism what could I have done better I would love to hear it because again it's only going to improve my future courses and if you did enjoy this course you got a ton of value out of it I

guess my one request would be to just spread the word share it right put it out on Twitter tag me in it I'll retweet it it really helps me out a lot right this is my livelihood now selling these courses so again if you enjoyed it um I guess the only thing I can ask is to share it

Loading...

Loading video analysis...