SwiftUI Ninja Training | Kristijan Kralj | Skillshare

Playback Speed

  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

SwiftUI Ninja Training

teacher avatar Kristijan Kralj

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

54 Lessons (6h 24m)
    • 1. The Course Overview

    • 2. How to Get the Most Out of the Course

    • 3. Create New Project

    • 4. Hello Onboarding View Explanation of the SwiftUI Syntax

    • 5. Introduction to View Containers

    • 6. How to Quickly Import Assets

    • 7. Build Onboarding Item

    • 8. Build Onboarding Tabs

    • 9. Get View Size with Geometry Reader

    • 10. Implement the Login Gradient Buttons

    • 11. Implement the Launch Screen

    • 12. TextField and Bindings

    • 13. SecureField View

    • 14. How to Organize Project Folder Structure

    • 15. Build Reusable Views

    • 16. Design TextField With Icon Using SF Symbols

    • 17. Navigation With NavigationView

    • 18. How to Quickly Build Password Reset View From Existing Subviews

    • 19. How to Show Alerts in SwiftUI

    • 20. Introduction to Animations Part 1

    • 21. Introduction to Animations Part 2

    • 22. Animate OnboardingView With the interpolatingSpring Animation

    • 23. Animate Login View With the Animation Sequencing

    • 24. Create the Animated Wave Animation

    • 25. Create the Animated Wave Background

    • 26. How to Use LazyGrids

    • 27. Implement the RegisterTypeCard

    • 28. How to Use EnvironmentObject and Navigate Programmatically

    • 29. Implement the RegisterPlaceView

    • 30. Slider Control

    • 31. DatePicker Control

    • 32. Finish RegisterMoveDetailsView

    • 33. Picker Control

    • 34. TextEditor Control

    • 35. How to Hide Keyboard

    • 36. How to Refactor Views

    • 37. Navigation With ZStack

    • 38. What Is MVVM

    • 39. Connect View and ViewModel

    • 40. How to Navigate Programmatically in MVVM

    • 41. Create RegisterViewModel

    • 42. Validate User Input

    • 43. Introduction to Lottie Animations, Swift Package Manager

    • 44. Show UIKit Controls in SwiftUI

    • 45. Implement Loading Popup

    • 46. Firebase Setup

    • 47. Register New User in the Firebase

    • 48. Login Functionality

    • 49. Password Reset Functionality

    • 50. Implement Persistent Login

    • 51. Implement the UserCellRow

    • 52. Implement RoomRow

    • 53. Display Room Data in List

    • 54. Fetch Room Data From Firebase

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

Do you want to build iOS 14 apps in SwiftUI, but don't know where to start?

Let me know if any of this sounds familiar to you:

  • You have watched a couple of SwiftUI tutorials on YouTube, but they don't explain to you all the basics, in a clear and organized way
  • Or perhaps you've been learning SwiftUI for a while, but you can't create applications that look like ready-made applications on the AppStore
  • Or you are a ninja in native iOS development, but you want to learn how to build beautiful applications in less time with SwiftUI

If any of this sounds familiar, you are at the right place.

What is SwiftUI and why is it a game-changer?

The SwiftUI is a new UI framework for the Swift programming language and it uses a declarative syntax to build user interfaces. With its easy-to-use syntax and built-in Xcode preview feature, the SwiftUI framework completely replaces the need for storyboard and auto layout.

With SwiftUI you can build your user interface faster and with less code. This Apple platform is becoming a big competitor to the traditional UIKit.

What do you need to know in order to start?

This course is not for you if you don't know Swift, or you are already very experienced with SwiftUI. Because I cover all the SwiftUI basics in this course.

You are going to learn how to build a SwiftUI app from the scratch.

SwiftUI Ninja Training will teach you:

  • All the basics you need to know about SwiftUI so that you know how to properly use the SwiftUI components to build beautiful apps
  • Spice your iOS app with animations fast and easy, so that it comes to life
  • Get real-life experience in SwiftUI by building the complex application with me from scratch - other similar courses teach you how to build applications consisting of 2-3 screens, but that's not how the real applications look like, is it?
  • Use the MVVM (Model-View-ViewModel) pattern in SwiftUI, to separate the UI from the business logic (avoid MVC pattern - Massive View Controller pattern)

After you finish the "SwiftUI Ninja Training: iOS 14 Edition" course, you will know how to build beautiful iOS applications in Xcode.

Some topics covered:

  • SwiftUI fundamentals - explanation of the syntax
  • View containers in SwiftUI
  • Use color assets to support the dark mode
  • Implement the launch screen in SwiftUI
  • Explanation and examples of using the most common controls of the SwiftUI
  • Navigation in SwiftUI
  • Alerts in SwiftUI
  • Simple and more advanced animations
  • New SwiftUI controls introduced with iOS 14
  • Model-View-ViewModel (MVVM) in SwiftUI
  • Lottie animations
  • Show UIKit controls in SwiftUI
  • Working with Firebase
  • Authentication with Firebase
  • Display data in the list view
  • And much, much more...

In this course, we will focus only on building a complete iOS app, but with the skills you learn, you can easily build macOS applications as well! You can even write a single SwiftUI code that will run on both iPhone and macOS devices!

Meet Your Teacher

Hello, I'm Kristijan.

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
  • Yes
  • Somewhat
  • Not really
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. The Course Overview: Hi, my name is Christiana and I'll be your course instructor. Let's just quickly Gore what you are going to learn throughout this course. We will build the Stacy. Stacy is a mobile app that makes it easy for you to find apartments, rooms, and remains in your next city. We will start with the basics or the swift UI. And as I explained you, every step of the way, we will build this onboarding view. After that, we shift gears, but just a little bit. And we'll practice your new Swift UI skills by building the login and password reset view. Next comes the most interesting part of building any UI. And that's animation will bring to life those previously. Three build screens. So the onboarding, you can see the animation here. Also login view. You see this slide in of our controls. And for the end, we will animate these animated wave background. Don't worry, this is not too complex. And our guide you every step of the way to show you how to build something like this and reuse it in your apps. After that, we'll take a deeper dive into Swift UI and explore different controls, such as new way of presenting, DateTime Picker, also new slider, and learned how to have a better architecture of your app by implementing the MVVM, which stands for Model View, ViewModel design pattern. Lastly, we will see how to implement the register and login functionality using Firebase and how to display room data in the list. And the end of this course, you have access to some useful resources. The full source code of the app, ebook with iOS interview questions, and the list of resources on how to improve the design of your mobile apps. And one more thing, during our journey through discourse will be accompanied by Ninja Josh. He doesn't talk a lot. But when he does, those are usually words of wisdom and you should pay close attention. Okay? We have a lot of work to do. So if you are excited as much as I am, then let's get started. 2. How to Get the Most Out of the Course: This course will teach you all the things you need to know in order to build beautiful iOS apps that have a clean and organized code. However, in order to get the best results, I recommend applying some things you learn in this course. Because as Steven Koh, we want said, to learn and not to do is really not to learn to know and not to do is really not to know. You really don't have to build the whole application in lower in order to learn something new. Even if you build a single screen, the knowledge you acquire. We'll stick deeper into your brain. Now where to find some mobile app ideas. There are a few places you can use. The first place is dribble.com. That's with three b. This is a site where you can explore thousands of redesigns and find inspiration. You can pick one screen from here and implemented. So you can select one designed and just try to implement something similar. And you'll see that you will learn much more by just doing that. The second one is similar to dribble.com and that's Behance.net. It also has thousands of designs that you can use as an inspiration while you building something new. So as you can see, the list is pretty, pretty huge. Next, if you know some kind of design tools like Sketch, figma or Adobe XD, you can find plenty of free app designs to implement at a lambda dot ninja slash freebies. So here you can see there are also multiple free designs. So you can just click on one design and click on Free Download. And you can open this in Sketch or Figma, and then you can copy these resources and implement in your app. These were all free options, but if you have some money to spend and want to have some premium designs, then you can head over to the site like RPubs.com. And you have all those free, but also a premium designs at your disposal. The price is starting from 1999 amount. There are also some alternatives to apply hubs, such as epic pixels.com or UI eight dotnet, where you could get all access pass for $189. The side contains premier mobile design resources. I will also leave a document with all these resources attached to this lecture. And also you have access to this in the free resources section. 3. Create New Project: In order to follow along by calling, you will need to have Xcode. I'm using version 12.2. So you would need that version or higher. If you have one of the previous versions of Xcode, that will also work fine. But some things in Xcode might look different than in this version. So let's create our new project, new app. Let's select App. Click Next for product name. I will enter Stacy. Demo. Theme is my team. Interface is swift UI. So the old option was storyboard, but we will use the new option, swift to AI lifecycle. We have two options. We have Swift UI app and the option that you are most probably familiar with UIKit update. We're going to choose the swift UI app lifecycle. And for language, we are going to use Swift. Hit Next, save the app. I'm going to sell it to the desktop and hit Create. Let's just expand the Xcode. So after you create your app, the first thing you see is the content view file. This is the first screen that the app will show after it's run. So let's just try to run the app to make sure that we see the content view. And we should see the output Hello World. There it is, Hello world. If you go back to the Xcode and let's just try to examining the structure of our project. In the first file we have here is Stacy demo app. And we can see that the content view is referenced from here. This abstract is the first thing the app will execute when it runs. So instead of having AppDelegate, the struct called Stacy demo app in our case, is what is the main file in the app. The abstract is now responsible for the app lifecycle. And which view we call From here that you will be the first few that will be presented on the screen. If we go back to the content view, you will notice that it has two structs. By default, Swift UI views declared two structures. The first structure conforms to the viewer protocol and describes the views, content and layout. The second structure declares preview for that view. We use previous to show the output of the view that we are building. So let's just hit Resume here. On this right side of the Xcode screen. This is also called canvas area. If we click on Resume, we will build the app. And these preview is what is going to be shown on this site. In case you don't have this. You can also show and hide this canvas area. So as we go along and make changes to our app and our views, the preview we'll automatically update. Let me just show. So instead of hello world, let's just type hello swift UI. And you can see that the view has automatically updated the layout of this Preview. And lastly, a tip. Sometimes the preview, we'll show you a red errors above this screen. What you have to do in that case is to try to build the project again or go to product and clean build folder and try to build the project again and hit Resume. And the preview will then likely show. If that doesn't help, then you will have to restart Xcode, which is sometimes the only solution that you can do. Or worst-case, you can restart the whole computer and then build the project again. And then everything should be fine with the preview. 4. Hello Onboarding View Explanation of the SwiftUI Syntax: I'm going to create a new swift UI view called onboarding view. So the goal is to start creating the onboarding experience for our users. So I can go right-click new file and add new switched UIView next. And here I can enter onboarding view. Okay, Let's click resume, the resume, our preview. So we can see this hello world. Let me explain you the syntax we have here. First, view. View is a protocol that's trucks conform to where we want to display them on the screen. In our case, our or warding view is going to take the whole screen frame. But we can also have some smaller views that are displayed only on the sections of the screen. Finally, every control with display within our view is also of you. In this case, this text, this text Hello World. This is also how you, the viewer protocol only has one property, which is this body. This describes the actual layout of the view. Some of you means that we are returning a view from that property. But the actual type is not relevant. It could be text, image, button, or some container that contains multiple view controls. So we change our views by using modifiers. Modifiers are methods that change the original view. So for this view, I can change the text size by typing formed. And then I can type title. Title is our system predefined size. So if I type dot, I can see all the available options. So I can see body called caption, footnote headline, large title, sub-headline, title, title to Title three. I'm going to select title. One advice is to use those predefined sizes as often as possible. Next, I can change the text wait and set the actual text wait, too bold. So as you can see, immediately after I type bold, this helloworld is changed to bold. So instead of hello world, I'm going to put the actual text. So this is going to be fun places to live. Another way we can change how our text view looks like is by clicking on text, so and selecting it with Command Control. And this swift UI inspector appears. So I can click on Show UI inspector. And as you can see, I can change the font from here as well. So if I change it from title to large title, the text is actually changed and the code at the medically updates itself. So I'm going to put it back to title. But you can see also different, all other different options we can have to change our text so we can set weight, color. So you can see all these predefined colors. But you can also select custom color, alignment and line limit. So there are plenty of options. There is also a third way we can change our view. This is by choosing this plus button, which opens the library. And here you have multiple options. So the first one is to select our view which you want to add. The second one is for modifiers. So if we want to change the foreground color for this text, we can choose foreground color and put it here. And this will change our color to blue. We also have some other options, such as snippets. We can select from images. And if we have a color palette defined, we will see how to do that later. We can also select the color here. I'm going to change this color back to black. Now, out of those three options I presented you, I'm going to use the coding way. So I'm going to type new views and modifiers here. Within the struct. I can also set the padding around this text. So this is just to get a little bit more space around this text view. And if we really want to learn how to build advanced views, then we need to learn how to use the view containers. 5. Introduction to View Containers: So like I mentioned in the previous lecture, when we are creating our Swift UI view, we have this body property that contains the layout of our view. This body returns just one view. So if we want to have multiple views without within our body, then we need to use containers. Containers group views together horizontally, vertically, or one on top of the other. There are three main containers in Swift UI we can use. Those are called we Stack, HCI Stack, and z stack. First one is we stack. We stack layout children in vertical list. Next one is eight stack. A stack layout children in horizontal list, so they are all positioned within the same horizontal line, but they are positioned one after another, as you can see on this image. And finally, we have z stack. The stack container puts its children views one on top of the other. You will see in multiple places how you can use the stack to have something in the background, then put other views on the top. This is used in order to get the design. We want. New things. In iOS 14 is lazy, edge age greed, lazy, we agreed. So these are greed containers and they layouts children in agreed. We will explore them in later sections while building the registration flow views. Now, let's embed this TextView within restock. So I can go to the text, click Command or Control, and click on Text and have option to embed in age stuck. We stack and the stack. If you don't see this z stack, this is added in Xcode 12.2. So make sure you operate to have this option as well. So I'm going to embed in the stack. And just to explore this we stack. We have different options for rings. We stack. We can set alignment, spacing and then the actual content is placed within. So let's now create another view. And below this first text, I'm going to add another text and have content fine, great, rarified places and people to share a home with. This text is going to have font of body. So this is a bit smaller font size. Then we can set foreground color, let's say, to black as well. Or if we leave it without setting foreground color, it will have the predefined color. Next, let's add some padding. But instead of setting padding to all four sides, what we can do is also just select the horizontal and define how many empty space we want to have. On leading and trailing site. Like I mentioned before, we have some options. So let's just explore them quickly. The first one is alignment. So this just displace the Children controls center leading or trailing saw by default is centered. If we place them leading, you can see they are positioned by leaving site or trailing. You can see the output here. Other option we have is spacing. So this is the actual space we have between our children controls. So if I said 50, you will see there is our greater distance between these two text views. In case we want to fix the indentation for our view. We can select that view and click on Control I. And then this is automatically repositioned correctly. Every time we do that, you can see that automatic preview updating was paused. We need to resume that. One other thing when it comes to foreground control is there it has one other color predefined, which is called primary. This color is useful when we switch between light and dark mode. So if we put foreground color as primary in the light appearance, this color will be black. But if we change the appearance to dark, which we can also do in preview by hitting this inspect preview. And then we can select color scheme. And if we select this to black, you see that this foreground color is automatically change to white color. Text is left black. So that's why you don't see it when you change too dark color scheme. But we also said that through primary, then the text is also appearing here. After we have changed the color scheme of our preview, too dark. The new modifier has appeared for our on-boarding view inside the preview provider. And you can see that preferred color scheme was changed to dark. So there is also this option that we can modified our preview inside this preview provider to change color scheme and all other options. So we can also, for example, change the device. I can select, for example, smaller device. And then preview device was changed in our case to iPhone 8. And after sometimes preview, we'll also build the code and show how the output would look like in iPhone 8 device. I'm going to remove these two lines. So go back to the default preview device. 6. How to Quickly Import Assets: In order to have advanced designs in any app, what we need is some images and some colors. So now I'm going to import all the assets we are going to need to build some advanced views. I'm going to click on assets, right-click Show in Finder. And I have this Assets dot z acids. So I have prepared all the assets. I'm going to need to build our views. So what I can do is to replace this original folder with the folder that has all the images necessary in case you are coding along. I'm going to attach these assets to the, to this lecture, to the resources. So now once we go back to the Xcode and two assets, we have all the things I have just important. The first one is accent color. This color represents the main application color. If we go and inspect it, we can see that it has this following hex value. Next one is an icon. So these are the icons that are used for this application. Then we have colors. I'm going to go back to course folder in just a minute. Let's just explore all other things we have. So these are the icons we are going to use. Also, there are some images we will for the onboarding, we will use these OMB fine place or MB alike and OMB Mitch. So we are going to have three onboarding items within our on-boarding view. Next, there are some roommates. These are just some people images. And finally, we have rooms. So these are just some sample data we are going to use to achieve our design. If we go back to colors and you can see that I have defined this color palette I'm going to use. So Sal colors are just universal, meaning that they have the same value if we are using them in dark or light periods. But for example, some other colors, such as text. I have defined two values. So the first one is for any appearance. This is the color that we will use for the light mode. And when we switch to a darker periods to the dark mode, then the text color, we have this slightly gray. Value. Same thing is for, let's say, text. For dark, for light periods, we have this dark blue for darker periods. I think this is just white-collar. Yeah, it is. Let me show you how these colors are automatically changed once we change the appearance. So for our text, instead of primary color, I'm going to use the color which has name, title. Let's resume in the preview. And you can see that the color has changed. Also for our description. I'm going to use color that has named text. You can see this is some kind of gray slash blue color. And if we now change the appearance to, let's say dark, then you can see that the colors are also changed to have the values set as dark. Okay, now I can delete this. And finally, let's add the on boarding image for our first onboarding item. To define image, we use image control. And we need to specify the name. I'm going to specify OMB, find place. You can see the image automatically appears here. There are different properties we can use for image. First one is resizable. If we select the resizable, this means that we can change the size of our image. Next. We can also set the frame. So frame means which size that we want this image to have. For example, for height, we can select for now 300. And you will see the image will update. Also. We can set it different aspect ratios so we can scale. To fit. You can see the image will scale itself. Or we can scale this to fill. And this will fill all the available space. Another important thing is that we can have multiple modifiers that are the same. So for frame, we can have these frame override, which takes with height. But there is also another frame override that has min-width, max-width, min-height, ideal height, max height. So there are two of them. And we can select these one to select the max width. And for Mac suite, we can also select some kind of value. But there is also another useful option, which is called Infinity. Infinity just simply means take all the space available. Actually, I can set this to 400 to have a bit bigger image. As you can see, we stack will position all these elements in center of the screen. If you want to move all these elements to the top of the screen or to the bottom of the screen. There is another useful view we can use. This view is called spacer. So I'll, spacer will push all these views to the top. If we select this spacer and put it as the first element, then this element will push all the remaining views to the bottom of the screen. We can also have multiple spacer elements within, within our stacks. And we can also put them wherever we want to solve. We put them between image and text views. Then you will see these empty space between image and text. That was spacer view. I'm going to remove it since it's really not needed here. We will put some other controls to the rest of the screen. Well as change, I'm going to do here is for this description text, I'm going to set the multi-line text alignment. As you can see. At the moment, text alignment is leading. I'm going to change this to center, to position all lines in center. 7. Build Onboarding Item: We have made great progress already. And I think CAN into Josh agrees with me. We are currently displaying one onboarding item on the screen, but in order to display three of them. So first, second, and the third one, we will create a struct that will hold onboarding item information. So let's create a new struct. So right-click new file, swift file. And I'm going to call this onboarding item. So we have struct called onboarding item. And this struct, we'll have three fields. It's going to contain image name. This is going to be a string. Second one is title of our on-boarding. And the third one is description. And this is also a string. Now let's go to the onboarding view and just create some data for our onboarding. We can create a new array called onboarding data. This will be an array of onboarding item. So we will create array that will have three items. So first one item is the item we are currently showing. So image name is OMB. Fine place. Title is find places to live and description. Find great verified places and people to share the whole width. Great. The second one, it has image. When B match. Title is match. Your preferences. And description is tell us your preferences and match with the right people. I'm missing comma here as well as here. And the last onboarding item is the item for OMB, like image name. Title is going to be like minded. People. And description is lived together. We'd people who inspire like you. So every time we add a new property to our views, we need to update Automatic preview. And now we are ready to create tab view that will display this onboarding items. 8. Build Onboarding Tabs: Great. Now we have all the data we need to build our entire onboarding flow. But before we add the top view that will switch between those onboarding cards, what we can do is to extract these elements we have into separate new sub-view in order to reuse this exact structure. So we want to preserve this image and these two texts and all these modifiers. And we will have some kind of loop. And we will go through these three items and showed them inside this onboarding flop. The first thing I need to do is to add another. We stack so that I can use this stack to extract subview. I have the extracted view, which I'm going to call on boarding card. So anytime you find that you can reuse some views, in other views. Or if you just want to clean up your main body property, you can extract the subview and have this structured into a separate struct. This struct, I'm going to make it file private since I don't want it to be available outside of this file. Also, what I can do is to define our new variable called onboarding item, which is type of onboarding item. And I will use this onboarding item to replace this hard coded strings. So instead of image, I'm going to have on boarding item, that image name. Instead of this title. I'm going to type On boarding item dot title, add. Lastly, here, I will type onboarding item, that description. Now, this onboarding cart will complain since I need to add an argument which I have defined here. So I need to add new onboarding item. For now. I can hard-coded these 2 first element of the onboarding data. So if I click on Resume. There is no change to the actual preview. Only the structure of our view has changed. Like I mentioned before, to show the onboarding flow, I'm going to use view named top view. So I can Command click on the on boarding card. And first thing I can do is to bed in a container. This container is going to be top view. So by default, W shows this bottom bar. That is usually see on many apps that has icon and name. What I can do is to change the style of this stack view. So I can use tab view style modifier. In here. I can pass the style I want to have for this taboo. For this tabu, I will have style named page tab view style. And in the display mode is the argument. This is going to be automatic. I also want to show the index few at the bottom so I can know on which current onboarding cards the user is placed. For that, I will use the modifier called index view style. And the style is named Page Index new style. This has background display mode. For the background display mode, we have several options. So always automatic, interactive, and never, I am going to show always this index view style. Now if we copy and paste this card, we see this index, your style. In order to interrupt with the top view and this index, I can hit this Play icon. This is a for making our preview go into live mode. And now I can interact with the layout. Of course at the moment, I am displaying the first item for all three onboarding cards. I can show that. I can change that by changing the onboarding data we are currently displaying. So now I have this onboarding flow. This way of looping through the on-boarding data is not optimal. And we can certainly do better than that. The other way to loop through some data we want to show or in our views is to use the forEach element. So I can command, control on the on boarding card and click on, Repeat. This will embed the on boarding card in the for each element. And here, instead of 0 to five, instead of five, I can specify on boarding data dot count. Here the item is index. So I can use that index to get the current element of the array. So I can use it for On boarding data index. And instead of this hard-coded first element from the onboarding data, now I can specify element and I achieve the same effect as before. Only now ion duplicate the code, but use foreach loop to populate these onboarding cards. 9. Get View Size with Geometry Reader: At the moment, we are hard-coding the image height to 400. And if we change the display to hyphenate, you see that the screen is fully occupied and there is no place at the bottom to add two extra buttons that we need to add four register. And for login, we would like to know the actual size of this onboarding card, and then divide that with some number in order to make the image a bit smaller. And in order to get the view size industry to UI, you can use the geometry reader. Let me show you how. So I will position myself to the stack, then Command Control embed in here. I will add geometry reader. So geometry reader is a view that occupies all the available space within the parent view. And geometry reader pass the geometry proxy variable, which has properties for wheat tight position, et cetera. So we will pass Geometry variable. Now using this geometry, get the actual size. So geometry dot size, dot height. To use all the available height for image. As you can see, this is a bit too large, so I'm going to divide this with 1.5 in order to make this image smaller. Now the image will be adjusted based on the geometry size. So once we add extra buttons to the, to the bottom of this onboarding view, then the image will be a bit smaller. We can also just quickly inspect the geometry and its properties. So geometry size, that height. You can see what height do we get back from the geometry. Also. You have access to it. And now let's revert these changes. So I'm going to use onboarding items. That title here. 10. Implement the Login Gradient Buttons: Okay, let's finish this onboarding view by adding two missing buttons. At the bottom. I'm going to delete this previous device, etc, to default. And now here below, I can add new view called button. Button has two main parameters. First one is action and the second one is labeled action. This is the code that will be executed once we tap on the button. And for the label, we can put whatever we want here. So I'm going to put text view and say login. I'm going to add some padding around this button control. And at the foreground, color of text, so color text. You will see later sections how to tap on the button and then execute some code. We can try to just preview something. So let's say button that we can try this by running the app. I'm just going to run the app. The actual first view is still the content view. We can change that by going to the Stacey demo app. And here sort of content view. I can select the onboarding view. Content view is not needed anymore, so I'm going to move it to trash and try one more time. So now if we tap on login buttons, you can see that this action is being executed. The final piece is another button that has Getting Started. Text. So action, again. For now, I'm going to leave it empty. And here the actual label, it's going to be text. That has text. Get started. Let's just resume the previous older. We can see the output. So we have our button here. And now we can modify this text for frame. I'm going to have it of MUX we infinity, meaning that it's going to take all the available space on horizontal axis. I will also add some padding around it. For foreground color, for the text color. I'm going to have a white. And now the text is going to be temporarily invisible until we add a background. So for the background, we have multiple options. We can specify just one color, or we can specify it. The gradient. I'm going to use the linear gradient in order to have the Gradient button effect. So this is a linear gradient. And linear gradient has some parameters. So this is a gradient, start point and end point. Let's just first fix the start point, sorry, point is leading. So this is fine. This is the left border here. And point trailing. This is the right border here. So this is fine. But you can also have different options. So you can start at the center or we can start but top leaving, for example. And you can see the actual gradient changes. So if you need to have some custom gradient in some custom direction, you can always modify starts and end point. I'm going to leave it to trailing. Sorry to leading and trailing. And four colors instead of color red and color blue. Here, I'm going to have gradient start. And here the second color is gradient. And so this is the effect I want to achieve. Also, what is also a possibility is that you can have multiple colors to have different gradient. So you can, this gradient takes an array, meaning that you can have multiple cores. Let's just style this background a little bit. I will add corner radius of 10 and add some padding for horizontal, so of 20. Let's see. You can see the corner radius of 10. Also. One other thing you have to have in mind while making style changes to your views is that the order of modifies matters. In my case, bedding comes before the foreground. If we change the order of background and padding, you will see that you get a totally different output. So first, the background is applied to these texts. And after that, you get this padding. So you see by this blue line where the actual view ends up and everything around this is spinning. 11. Implement the Launch Screen: We will wrap up this section by adding the lawn screen for our app. In order to do that, I'm going to create a new file. And this file is going to be launched. Screen hit next. Plot on screen name is just fine. I will go to Stacy demo project and select that launch screen file. And here, instead of having this label, I'm going to add a new image image view to this. And for imageView, I'm going to select Logo inventory on. Let me just position this in center of the screen. So horizontally in container and vertically in container. I'm going to add these two constraints. And now when I launch the app, we should see this launch screen. Yeah, here it is. And now after that, the onboarding view is presented. Rather cool trick I'm going to show you is how to avoid having these strings four cores instead of, we will have type-safe colors. Here. I have prepared the core extensions file. So I'm going to drag and drop it to the app and copy this item. Add to Stacy them a target. And what the score extensions contains is the extension of our core class. I have defined static fields that change all these core assignments to type-safe variables we can use. Using this is pretty easy. So instead of color, gradients start. I can type color that gradient start. And instead of color gradient, and I can type color dot gradient and the actual view, it's not going to change. But the way how we access these colors is much safer since we won't end up mistyping the text, the core names. So this is text. And we also need to change our on-boarding card. Instead of color title. We can just type title. Instead of color text. We can type texts. And now we can reuse these whenever we want to have the color from our assets folder. 12. TextField and Bindings: Okay, then to create our new view called login, you saw, let's go to new file, user interface section and swift UI view. And this view, I'm going to call it login view. We are going to reuse this text to have the title on our Login view. This is going to be high. And in new line, we will have welcome back. Hit Resume to see what we have so far. We have this. Hi, Welcome back. Let's just embed this in we stack. So the whole screen is going to be implemented in the racetrack. And also for our title. We want to have it a little bit bigger and want to have it positioned on the left side. So we want to have it trailing alignment. What we can do is to embed these texts in each stack. And in order to push it to the left, I can add spacer. So if you remember from the last section, we use spacer to push views two different size. So since we are using h sec, we are pushing these texts to the left. Okay, let's just modify this text for font. I'm going to use large title for font weight. This is going to be bold. So another option is to just have it like cobalt. For foreground color. We are going to use a custom color of text and we will add some padding. I'm going to have biting at the bottom of 30 and also add some padding to the leading side. So to the left site of 20. Instead of having text, what I can do is have foreground color of title to get this slightly darker title. Great. Next, Let's continue with implementing the login view by adding another stack. And we stack, we are going to put our text field. So in order to accept user input, we use text field as one of the fields that we can use to have inputs. It has different ways to initializing this text field. I'm going to use the first one that uses localized string key and binding of string. So for Title key, this is the placeholder text we want to enter. So this is going to be email address. And for text. So this is the binding. Binding means that we are connecting this text value of our text field to some variable. So what I will do now is to define our new state variable. Call it e-mail. This is going to be type of string. And the initial value is going to have empty shrink. Our state keyword is our property wrapper, meaning that it extends the functionality of our string variable. In this case, it lets us update the string value dynamically. And that value is preserved whenever the view refreshes. Because every time we change something, so every time the user enters our new character in the text field, these state variable is updated, but also the text field. This entire view is redrawn again. And with the state variable, we preserve the values between those updates to the text field. In order to pass the email variable to the text field, we use the annotation of dollar email. Let's also see what an intro Josh can teach us about the bindings and abound this dollar sign. Dollar sign means that we are creating our two-way binding between our view and our state variable. We are extending, establishing our connection between our text field and our string variable that will hold the information about what user has inputted in that text field. To it. Two-way binding means whenever the state variable is updated, the view gets updated. And whenever we update the view with the new value, the state variable gets updated. This way, data is the single source of truth in the Swift UI. So data determines how the UI will look like. Also, views cannot be referenced directly to change them, but instead, we are using data. In this case, this is, this is going to be state to update the views and UI. So let's try again to update this login view. And now we have these email address text field. We can also style this text field. So we can change the font, let's say for formed, we are going to use Title 3 to make the actual formed a little bit bigger. We can add some padding of 84 actual textile. There is a modifier called TextField style that has different input options. So for TextField style, documentation says that we have different option, sorry, have default text field style, plain text fields style, rounded border TextField style, and square border TextField style. Let's just examine how this shapes our actual text field. So the first one is the default text field site. So this is the default output that we had already. Next one is plain text field style. So this is, so this looks fairly similar. Next, we have rounded border, TextField style. This will add the slight border to our text field. And finally, we have square border TextField style. But we get the error that the square border text we'll style is unavailable in iOS. So instead of using this TextField style, but we also can do is to apply our own style to the TextView to modify it a little bit. 13. SecureField View: Let's add the custom border to the text field. One way to achieve this is using the overlay. Overlay is a modifier you can use to put some other view on the top of our current view. For our overlay, I'm going to use the rounded rectangle shape. Rectangle shape is going to have corner radius of eight. And I'm going to add a border with stroke. Stroke. It's going to have color of text. And we are going to add some opacity. So this is our value between 01. I'm going to put 0.742 argument linewidth. This can be one. So with this, we got the customs border around our text field. Finally, what I can do is to add the horizontal padding, let's say of 20, to move this text field. Next for inputting passwords and similar sensitive data, we use variation of text field, which is named secure field. It acts similar as the text field. So we enter the placeholder radio. This is going to be password. And for text, we need to define another state variable. So instead of State email, for this password, I'm going to use state variable named password. Let's try to build the preview. And try again since it didn't update my first attempt. Great. What we can do is to copy and paste the style to have the same look and feel for our security field. What I missed is the font and bedding modifiers. The next thing we need to add is the login button. And we want to have the same style as this Get Started button. So in the next lecture, you're going to see how to reuse this style to apply it to the New button that we will create. 14. How to Organize Project Folder Structure: Before we move on and continue with the login view implementation and add multiple new files. Let me show you one way how you can organize your project folder structure. Because having everything in one folder can get soon messy. Some people like to organize projects structure by layers and type files. So they have folders for interfaces, view, models, views, etc. I like to organize code by modules and functionality or features of the app. This approach was suggested by Robert C Martin. This is all, he's also known as alcohol Bob. I'll put links if you want to learn more about this approach. So what I usually have our three top folders. The first folder is called application. In application folder we put any applied files, initializers, or configuration files. This folder usually only contains a few files. In my case, I'm going to put Stacey demo up here. And for now, launch screen. Next, we have folder name. Colon. Colon is used for oral common utility and view components grouped in sub folders. Some examples for these groups are controls, models, exemptions, Persistence. I'm going to create a couple of sub folders here. The first one, I can call it extensions. And I'm going to put color picker. Here. Also our adds another group for models. And in this model, I'm going to put my onboarding item. And finally, the third top folder I'm going to have in this structure is named modules. Four modules. You can think of one module as one screen. In the modules folder, you organized screens into logical groups, which are basically sections of the app presented to the user. Re module folder usually contains the view and view model files. In my case, I'm going to create two new modules. First one, it's going to be on boarding. And for now, I'm going to put on boarding view here. And the second module is going to be a login. And I'm going to put the login view here. I look, I like to group the files this way because usually when I change the view and I'm using the Model View, ViewModel better, which you will learn in the later sections. But I have to do after I change the view, I also sometimes need to change the viewModel. So I like to group together these files that change together. This way, it's easier to access them. 15. Build Reusable Views: Like I previously mentioned, I would like to achieve the same layout for the new login button. As for the Get Started button on the on-boarding view, the easiest thing would be to copy and paste all this code. But we can use it instead using view modifiers. Let me show you how. I will create a new folder under common called modifiers. And here I'll create a new swift UI file. So new Swift UI file. This file is going to be called Gradient button style. I don't need the preview for this. And instead I'm conforming to view all conform this Gradient button style to view modifier. So you modifiers allow us to reuse our set of modifiers we have. We are not conforming to the view modifier protocol. So what we need to do to add another function call body that takes the content. So this is the view we are going to change and we return the modifier view. So I'm going to take this content and apply some custom modifiers to it. The modifiers I'm going to apply. These are, Those are all these modifiers we are using for the Get Started text. So I can copy and paste that here. So this way we can reuse all these modifiers. Okay, hit Save. And I will also make an extension to the text. So make our function called text style. In order to ease to have easier access to this view modifier. I'm going to define the generic type called style. This is a type of your modifier. And the style, I'm going to apply it to our view. And this will also return of you. Here. I'm going to apply modify content. So in order to apply a modifier to have you reuse modify content. So the content. It's going to be self. So this is going to be our text view and modifier we are going to apply. This is going to be the style. We pass to the text style. Let me show you how to use this. Now, instead of using this text modifiers, we are going to use the new modifier we have built called textile. And for view modifier, I'm going to say use Gradient button style. If I click on the resume, the button hasn't changed by now, but now we have Gradient button style that we can easily reuse. So let's see how easier is to reuse this by adding a new button called login. And voila, we have the new buttons styled here. So this is great since we can use this Gradient button style in multiple views. So you will see as we go along, we will keep reusing these Gradient button style. Another way to reuse views is by extracting them into subunits. In my example, this welcome back, title and all these modifiers, I would like to reuse that so that I can have the same title, look and feel for my other views. So what I can do here is to extract this age deck. We command and control. And I have oxygen extract sub u. I'm going to call this screen titled view. By default, screen title is extracted within the same file. And one other, one other change I am going to make is that I'm going to make this text as a parameter that we are going to pass while initializing the screen title so that we can keep reusing this view. Instead of this text. I'm going to put a title here. Now, I will add the title here. I have pasted also here, so I'm going to remove this. Try again. But I don't like this title. I don't think this is necessary since the view itself tells me that I need to pass some kind of title. So instead of having this initializer, I will add the initializer to change my initialize a bit. So I don't have this title here. But instead, I'm going to set the title from the initializer. And now I can fix that. 16. Design TextField With Icon Using SF Symbols: Next, it's time to add some icons to our e-mail address, text field, and our password field. For that, we are going to use built-in SF symbols. S0 symbols provides a set of or 2400 symbols you can use in your mobile app. Apple designed SO symbols to integrate easily with the San Francisco system formed. So this means you can style as a symbol. Similarly, how you would style all those texts use, you can download the SOS symbols to the Apple Developer website. I will attach the link to this lecture. So here at the right side, you have download the app and make sure you download the SOS symbols. Version 2.1 or greater, since this comes with additional symbols. Once you install and open the app, you'll get access to all these icons divided by different categories. You can see all the categories here to the left. And what you can do is to search for all those icons you need. And also you can preview how the icon would look like when we apply some font weight modifier to it. So for ultralight, you will see that the icon have this thin borders and shapes. And going back to semi bold and also black, you see how the icons change. For the email address text field. I'm going to use the envelop SF symbol. But instead of black, I'm going to use the regular size of the envelope symbol. What I can do is to copy the name of symbol and then use it in my app. I'm going to put this symbol inside this overlay, this rounded rectangle. So what I can do is to wrap the entire text field. We ate stack. And instead of applying the overlay just to the text field, I can apply the overlay to the aid stack. And now, in order to use this sf symbol, we use it by specifying an image and for initializer reuse system name. And here I based my envelop and I get this icon in order to get the exact same size as this TextField. What I can do this too. Apply the font title here, and this will make this icon bigger. Also. I can change the foreground color, so I'm going to use color dot text, but add some opacity of 0.7. So to have this slightly gray icon. And instead of repeating this font titled 3, 2 boat, image and text field, what I can do is to cut and paste that here. So if I specify the on the age stuck deformed, titled three, this will be applied to boat image and text field. Also, this bedding. I will add that to the stack so that I can adjust the overall petting. I need to do now the same for the secure field. So I will add the H stack that I will wrap around the secure field and have this font bedding overlay and another padding applied to the eight stack instead of secure field. Again, I'm going to start with image. And system name is going to be key in order to get S0 symbol key. Same thing. I will apply this foreground color to my key image. And you're in order to address, email address and password, the start of these placeholders. I'm just going to apply some leading padding to the secure field. Let's try with six. Okay, a little bit bigger, so eight. Yeah, it looks fine. And finally, some additional options we can set to the text field only is to change the keyboard type that will be shown. Once we go to the text field. Once we want to enter something as the e-mail address, our keyboard type is going to be e-mail address. We are going to disable auto capitalization and disable auto correction. So once we want to enter this e-mail address, we will have the e-mail address, keyboard type. This email address looks like something we could easily reuse for our password reset view. So here I'm going to extract, extract this as another sub u. And I will call this e-mail field. And whenever that email field is extracted, some of you. But we can't find these e-mails state in order to pass state from parent view to the child subview, we use something that's called binding. So we have another property wrapper called binding. And we use this binding in order to pass the state from parent to child. And as we type something to the email address text field that will be stored in the email bindings, but also that will propagate back to the state. So we will change boat e-mail state and email binding at the same time. And here now I need to specify email Ben binding. For that, I'm going to pass email while lasting. Instead of having these two structs, these two subviews. Inside this login view, I'm going to create a new folder for four subunits. So this will store all the subviews I can reuse inside this mobile application. And here I will store my screen title. So I need to add new file, new Swift UI file called screen title, and cut and paste existing screen title to this screen title. Here we are missing the parameter. I'm just going to type hello world. Quickly preview that. Everything looks just as before. But also I will add another group called reusable. And here I will put my email field. This reusable views will contain all views I can reuse across multiple apps. So my screen title and how it's modified. This is reused at only Stacey up level. But my reusable views, I can use that across multiple apps if I want. So with this, I will build our repository of subviews that I can quickly reuse across multiple apps. With this, my future app development is going to be faster. Here. It's missing the argument for email, email call. So let's add this and you're ready to add the binding in previews. What we can do is to hit constant. And here I will add email, let's say Josh, Swift UI, ninja. And if I resume this, I will see this e-mail. But finally, the spending is not something I would like to have inside my subviews. I would like for you to stretch to the whole width of the screen. And if I need to make some kind of adjustments to suit my current view, I can apply that padding to this address. Lastly, let's add some spacing between email address and password. Do you remember how to do that? So we can specify spacing of 616 in order to make the space between these two fields bigger. 17. Navigation With NavigationView: Now let's explore how you can navigate between different Swift UI views in Swift UI. So I'm going to create two new, two new modules to new views. The first one is going to be password reset view. So new module, password reset. And here I'm going to create a new swift UI view called password reset view. Let's also create the register. You will also create the register module. And here I'm going to create a new swift UIView. I would call it register type view. So during registration, I will have multiple views to build the entire user registration flow. But this register type u, this is going to be the first view in my flow. I am going to change this text for now just to say resist register. And for password reset, I'm going to type password reset. In order to navigate from our Login view to the password reset. I will add a new view called navigation link. Navigation link takes two main arguments. First is destination. In our case, we want to go to the password reset view. So this is the destination view we want to navigate to. And for label, this is the view we specify for our navigation link. So for our navigational link, I'm going to add new text that says forgot password. It will have foreground color of Next. And let's resume to see how this looks like. So this is currently positioned at the center, but we want to position it to the right side of our screen. So we can do is to embed in each stack and add spacer to move it to the right. Now our forgot password is positioned to the right. Let's just move it a little bit to the bottom. So I'm going to add padding, top. Auf den and also horizontal padding of 20. And finally, let's just move the login button to the bottom by adding the top padding to our text of 20 or less. Now preview how the forgot password. We'll navigate to the Password Reset fuel. If we preview the view we have and tap on the forgot password. You can see if we don't have any action performed. That's because navigational link alone is not enough. If we want to navigate to another real, what we need to do is to embed these whole we stack in our container. That's called Navigation View. So now if we want to navigate to the forgot password, this works. You say, you'll see, you'll get the Navigation Controller functionality. So you get the automatically back button in order to navigate from password reset back to the login view. Finally, let's add the button down below to navigate to the register V0. So I can add spacer that will move all my views for the top. And everything below spacer is going to be moved to the bottom. Here. I'm going to add and eight stack that we'll have to text. First text says, don't have Stacey, account, foreground color of title. And here after this text, we will have navigation link that will go to the register type view. And for label, I'm going to add another text. We sign up. For argon core is going to be blue. So now we have this sign-up functionality down below. Finally, let's just add some bottom padding to our age stack to move it a little bit higher. Let's also preview how this works. So top on, sign-up, move us to the register view. 18. How to Quickly Build Password Reset View From Existing Subviews: Another way that we can perform navigation within the swift UI is by using the full-screen color modifier. Let me show you how. So in my top we stack. And just after top stack, I'm going to add full-screen color and select the initializer that has it is presented and content for is presented. This is the binding. That is, this is the bool variable that indicates when do we need to trigger the full screen cover. So I need to add another state variable. Another thing that is good to use in your own code is to make those state variables as private, since they are really not meant to be shared across multiple views and structs. So it's better to have them as private. Name of the variable is show login. And by default, this is set to false. We want to trigger the show login once we click on the Login button. So I need to find the login button. And here instead of print, what I'm going to do is to set show logging to throw. Another way to change the show login variable is by using toggle. So I'll toggle will change the state from false to true. And if the state is true, then it was Celtx dot state to false. So full-screen color is presented. Once show login is set to true. And as for the content, the content we want to show is our Login view. Let's create a resume to build in the premium. And also we need to hit a live preview so that we can inspect and interact with the preview. So click on Login and you can see that the login view is appearing. If we try this in the simulator, you will see that this also works. We are now ready to build the password reset view. As always, I will start by embedding everything in the stack. I can also indicate with the comment that this is the parenthesis of the stack. This is the ending parenthesis. And just above this password reset, I'm going to add the screen title view that we have previously built. Thanks for the screen. Title is going to be forgot. Password. And here, instead of this Password Reset text, I'm going to slightly modify this. So it will set, it will say, Please enter your email below to receive your password. Password, reset instructions. And by Ken, quickly modify this text by adding the foreground color of text and add the horizontal padding of 20. Rate. Our email field is next. So I'm going to add the subview called email field. And here I need to add the binding for this email field. This is going to be state. And like I mentioned, a good practice is to have these states as private vars. This is going to be email of string. And for now, the default value is the empty string. Let's pass that e-mail and adds padding of 20 to all size around the email field. Once we add another state, we need to build the password reset view. And we can see the e-mail is here. Last thing that we need is the actual button to send the e-mail with password reset instructions. So this button has two options. First one is sectioned and another one is content. Content is text that says send request. And I can style it using our Gradient button style. Last thing to add is the spacer, in order to move everything to the top of the screen. So you can see once we extract all the different subviews we use in other views, we can quickly build new views. So I have reused 1, 2, 3 reusable views to build this password reset view. 19. How to Show Alerts in SwiftUI: After the user has typed on the send request button, we want to show the alert that the help is on the way. And this is going to be presented as an alert. To show alert in Swift UI, we use alert modifier. I'm going to use the initializer which is presented and content is presented is bull. State. That indicates one, should we present this alert. So I need to add another state, private var, showing alert. And by default, this is going to be false. So this is the first argument showing alert for the content. The alert takes alert view as the content. And what we can do about this body is to create private func called display alert. And that function is going to return this alert view. Inside this display alert, we are going to construct the alert view, set it to set all necessary properties. And here we are just going to call this plate alert. This is another way to keep your code organized. So you don't have everything inside this alert content. Instead, you can use function to put the alert code here. Okay, let's click create the alert. As you can see, it has different options. So we can define title, message, dismiss button, primary buttons, secondary button, or just title and primary and secondary button. I'm going to use the second override for title. Let's specify the text success. For message, we will add the text. The email with the password reset instructions has been sent to your email. And if we don't specify anything for the dismiss button, and after we show the alert, it will show with the Okay button. By default, we just need to trigger the alert. Bye. Hitting toggle for the send request button. Let's resume the preview to see the alert in action. So I'll send a request. You get the success and the message. And we haven't specified this, okay, by default is displayed. If we don't have any other buttons. They are different options when it comes to our buttons. So you can hit Command on the alert to display the actual alert declaration. So we have default button, it has default style. We can have Cancel button. This indicates the cancellation. We have another override of the cancel and we have the destructive. This is usually with red text. For the button. I'm going to use this MS button and used the default button. And that will have text. Got it. So now when we hit on send requests, we get this button displayed here. One last thing that we can do is to specify what kind of action we want to do. After we click on this Got It button. For that, we use the action closure. And here is the code that it's going to be executed after we tap on this button. I would like to navigate back to the login view. After the user taps on the Got It button in order to programmatically navigate back to the previous view, what we are using is the environment property wrapper. So this is the environment state that we can use to perform some actions. We would like to access presentation mode of our current environment. And I need to specify the variable name. This is going to be presentation mode. The actual type of this presentation mode is binding. Presentation mode. And the action closure. We choose the presentation mode. We said, Get me the rep, value and dismiss the current view. So this is how you can programmatically navigate back to the previous view. But this won't work inside the password reset, since we don't have anything on stack instead, nor too. See how this works inside the preview, we need to go to the login view, hit the live preview, and go to the forgot password. You send the request. Got it. And once we top on that button, we will navigate back automatically to the login view. 20. Introduction to Animations Part 1: I'm going to step back for a moment from our main project and create a new project where you will learn and explore animations in Swift UI. I'm going to create a new app project and name this project. Sure, it can interface with AI lifecycle. So next, we're going to save that to the desktop. Let's resume the preview. And we have our Hello World app. Next, I'm going to go to the Assets and borrow this shrunken image from ninja Josh and put it here. And with help of this image, we are going to explore animations in Swift UI. Let's just change the simulator to iPad Pro. In order to get bigger canvas. On the right side. I'm going to decrease the Zoom 250 percent. And now Let's start by adding the stack. And here instead of Hello World text, I'm going to add a new image view. And the source of this image is the shrunken image that I have, that I have imported. At the moment, this is too big, so I can make it resizable and also change the width and height. For width and height, I'm going to declare our new variable, let's call it size. This is going to be CGFloat and the size is going to be 150. So size here, size here, and I don't need the alignment. Okay, a dominant, we have this image at the center of the screen. But it's a bit boring, just image, not doing anything. Let's start by rotating this image and see how we can animate the rotation. So for the rotation, we use the rotation effect. And we need to specify the angle at which we want to rotate this. So if I specify 45, this is going to rotate the image. Now let's see how to animate this. When it comes to animations in Swift UI, every animation has three main elements. The first one is a trigger that will start the animation. Usually that's the state that once it's changed, it triggers the animation. For example, we can trigger the state change in when he, when we tap on the button. Or another common way is to put the states change inside the, on a peer of some view. Next, we need to know what's going to change, which modifier on the view. Usually there is our change in a numeric value. For example, we change the size or position of you. And lastly, animation kicks in only after we apply the animation modifier. We use this modifier to specify the options for the animation. There are different animation curves that Swift UI offers to you. Animation curve means the speed of animation for forming curves are easy. Easy means that animation starts slowly and then speeds up. Next we have is out. The animation starts fast and then it slows down towards the end. Linear means the animation speed does not change over time and ease in, out. This is the default behavior. The animation starts slowly, then it speeds up. And after that slows down towards the end. You can also have spring animations or define custom automation curve. So let's start by defining our new state variable for our rotation. I'm going to define it as rotate and set it to false. And on up here of our mistake, I'm going to change the rotate to true. Another way I can do this by toggle the rotate. So we want to apply this rotate to the rotation effect. If rotate is true, that means we want to spin our image to 360 degrees. Otherwise, if rotation, if rotate is false, then we want to have the initial degree and that's 0. And lastly, what we need to have these, the animation modifier. So we can specify the linear and see how this will look like. So let's click Resume. We can also change the duration of our animation by specify the seconds. So. If we preview this, you can see that it's bins for three seconds and then it stops. That was the spin effect. Next, let's explore how to animate the move of our image through the device screen. Temporarily, I'm going to comment out this rotation effect. And for our weeds tech, going to set the alignment to leading, to move this image to the left. Also, in order to get the device screen size. I'm going to wrap this week. We stack inside the geometry reader. So we can rub that inside the geometry reader in order to get the size. And we get this geometry reader parameter. We can use this geometry either parameter in order to get the device width and height. And we can move this image through out this horizontal axis. The easiest way to do this is by specifying the offset. And we are going to define the X offset. So in order to animate the offset, what I'm going to do is to define another state variable. Let's call it one. And by default, this is false. So on up here, I'm going to change this. Move one to, toggle to true. And if power move one is true, then I want to move this image by the width of our geometry reader. So our geometry reader by default will take all the available screen size. Otherwise, the initial position will be 0, so there won't be any offset. And finally, in order to have some kind of animation, we need to specify the animation. Let's also specify the duration of three seconds. If we now resume this and preview, you will see that this shrunken image moves across the device screen. Here one, the only correction is that it moves to the whole width of the screen. But we want to take into account its size. So it stops at the end of this screen. 21. Introduction to Animations Part 2: So this was the linear animation. I can specify this as linear. Let's just have this as large title and add some padding. Let's see how this compares to some other automation, for example, is in. So I'm going to specify another state variable. Let's call it move to and copy and paste this image and this text in order to, for you to see how this compares to linear. So now instead of linear, we have is in end as well. I have to toggle here. Let's click resume. And you can see the difference between two animations. Linear moves to the whole animation cycle at the same speed. While is in. It starts slowly, but then it speeds up. And at the end, they finish at the same time. To other animation curves are ease out and ease in out. Next one is out. Again. I'm going to specify the state for this. Let's call it moved three. And here I'm going to change the move tree. So we can also have the same state that will trigger different animations. But we can also have different states for different views so that we can have better flexibility when it comes to animating and changing. When do we start some kind of automation? Here? We have ease out. Let's also preview this. You can see is out starts first, but then it slows down towards the end. And finally, we have is in ALT. So ease in, out. I'm going to specify another state for this animation. Let's call it more four. And here on a peer, I will also change for, by toggling it. Next thing, what we would like to have East to rotate our shrieking, why, while it moves to the right. So now if we uncomment this, we would like to have the rotation effect. But you can see that the rotation animation is being applied after the offset. And that's why you get this funky and undesired effect. But if we change these to animation to first have the rotation effect and after that offset, This works fine. We can also apply that to other images as well. And we will get the desired effect. So now the shrunken image, as you can see, it rotates. But they are all using the linear animation in order to rotate and offset when it comes to having multiple animations to the, applied to the same view at the same time, these animations can have some weird effects like not being applied properly. How we can fix this is by using the width animation, a closure instead of having this animation modifier directly applied to the image. Let me show you how this works. So here, inside one up here, I'm going to specify with animation. And I want to have these linear animation for my rotate effect. This means I don't need this animation anymore. So I can remove it from all images. And now this all works as expected. We could also apply this same width animation to other move states and toggle that instead of width animation, this means that we don't need this an emission of sit here, but instead, we are applying this toggle through this width animation closure. There are also some additional options that you can have when it comes to animation. So you can have the delay. Let's say we specify the delay in seconds after which the animation we'll start. After we add the delay, we also need to specify the struct we are applying here. So you see now the rotate takes only after 1 second and rotates 1 second after the move is completed. Also, there are some other options for repeat count and auto reverses. Repeat count. So we can repeat this multiple times, the same animation. You can see now it's been in other direction. But if we said to ultra reverses to false, then it will do one time and second time, but everything will be done in the same direction. 22. Animate OnboardingView With the interpolatingSpring Animation: Let's practice what we have learned in the previous lecture about animations in order to animate different elements inside this onboarding view. The first thing I'm going to do is animate the opacity of our login button. By default is going to be opacity of 0. But once the view appears, I'm going to change this to one. So we need another state that will serve to animate login. By default, this animate login is false. But once we hit the moon, appear for our restock. So once the stack appears on the screen, we will call the function animate views. So we will use this function to define the animations. Let's call it animate views. It has no parameters and there is no return type. So for our login, we will have widths, animation that will be linear and duration. It's going to be two seconds. And within these two seconds, we will change the animate login to true. So by default, the opacity of our login button, it's going to be 0. But if, but if animate logging is equal to true, then we want to change that to one. Let's go into zoom and see how this behaves. So as you can see. So as you can see, it starts with the past is 0, but then it changes to one. Great. I would also like animate the offset for our button and our top view. So by default, they are going to be moved outside of the visible area of this view. And once the stack one appears, we will animate the slide in animation to the visible part of the screen. So I will create another state to control the animation of our Get Started button and our top view. I'm going to call this animate. And this is going to be false by default. And here in the animate views. I'm going to also defined with animation again. But this time, I'm going to use the interpolating spring. Animation. So this is the bounce animation you can have for your views. So it has this, alright, has two arguments. One is stiffness. Stiffness means something like duration of the animation. And dumping means the bounciness at the end. So once the animation, once the view gets to the destination, how bouncy it will be at the end. You have to experiment with these options in order to get the desired effects. I have experimented and got, got 48, that it behaves the best in my case. So inside with animation, I'm going to change the width animation through to true. And lastly, I need to define the offset. If the animate is equal to true, then there won't be offset. But in case of our top view, I'm going to move it for 100 to the right. Same thing for the Get Started button, but this button will be moved to the left before the view appears. And finally, let's hear, just add some padding to the top of 25 and also some padding to the bottom of 20 just to have a bit more space around this Get Started button. And now if we resume this, you'll get this spring sliding animation. We can also experiment with stiffness and damping. If we have, let's say, smaller damping and we animate this, you will see that you get are really bouncy spring animation. But on other hand, if we specify dumping as really large value, there won't be any spring animation. So eight, I think works just fine. Same for stiffness. If we defined our really large value, then you will have are really fast animation. In other hand, if we define stiffness as really small value, you can see that it moves really, really fast. And therefore also, dumping is not applied because there was no great speed at which the views have a right around arrived. Like I mentioned, 48. I think they work the best. 23. Animate Login View With the Animation Sequencing: On the login screen. And you can see we have different animations that kicks in at the same time. And we need to do the sequencing of these animation. So Forgot Password and sign-up text area. They are just going to have opacity animation. But email address, password, and login. They are going to slide in at the different time. So the first the first one is e-mail address, often dot it comes password. And finally, we have a loading screen that slides in. Before we start. I think the animation, as you can see, there is a lot of views and the modifiers applied to this login view already. So the good practice is to extract some bits into subviews. I'm going to extract email address, password, forgot password in our separate view called login fields. In order to do that, I need to wrap up these. We stack inside another race tech and extent the sweet stack to also have this Forgot Password inside it. Now I can command control, click on the stack that I have created and extract this view. I'm going to call it login fields. So this has cleaned, cleaned, cleaned up a little bit, this login view. And here inside our login fields, we have these fields. Now, I'm going to make this file private struct, and I need to add another binding for email and password. So email and phosphorus are two new bindings that for now I want to pass to this login field. The important difference between binding end state is binding doesn't have a default value, but instead we are passing those bindings to the initializer. So for e-mail, I'm going to pass e-mail for password. I'm going to pass password. Okay, let's get the state to control the animation. The first element we want to animate is this don't have Stacey account sign up. Like I mentioned. I'm just going to change this opacity from 0 to one. So state private var of show login. And by default, this is going to be false. And on up here, I'm going to change, show login to true and change the opacity of the whole eight sec. So capacity is dependent on show login. If show login is true, then opacity is one. Otherwise the opacity is 0. Let's also specify two new fields for duration of the animation that we will have. So we will have duration defined as double. And I'm going to add zero-point tree as duration. And the second one, we are going to have some animation delay, and this is going to be 0.3. Now we can apply the animation property to the h sec. The animation is going to be is out with the duration which I have just specified. But it will also add some delay to have delay. Before this animation starts. Let's hit the preview. And you can see that we have this weird effect that this didn't change just the opacity from 0 to one, but instead, it moved from top of the screen, bottom on the screen. The reason why this happens is I think it's because of the, we have the Navigation View here. And Navigation View messes up with this animation modifiers. And instead of having this animation modifiers, we need to make our workaround to make this work properly, properly. So instead of having this animation modifier, we are going to move this animation to another place. So on appear. I'm going to create our function that will animate views and add the explicit width animation here. And here. Inside this width animation, I'm going to change this show login. And on up here, I'm just going to call animate views. And last step in order to fix this back, when Navigation View rubs everything and messes up with animation is Bye. Wrapping this, I mentioned inside the speech q dot domain, dot async. And now this should work as expected. So yeah, it works. So it just has changed the capacity from 0 to one. And we don't have this weird effect that these moves from top to the bottom. We will use the same state in order to animate our login button as well. So let's go to the Login button. And here I want to change the opacity depending on the show login state. So if show login is equal to true, then I want to have a capacity of one. Otherwise 0. You can see the effect right away. And also we will add the offset to our button. So if show login is equal to true, then, then there won't be all set. Otherwise, we will have offset of minus 200. So this is the effect that we have with offset and opacity. Next, let's animate this e-mail address password and Forgot Password field. We can reuse much of the animation effects that we have defined inside the login view. So I'm going to copy and paste that to our login fields. I need to also call this animate. Views. Inside this one appear. So here we will animate our views. For show logging. I'm going to reuse that to change the opacity of our forgot password. So this is the same animation that we will have as on this stack. At the bottom. We are just changing the opacity. Let's resume to see the effect on the forgot, Forgot Password. So you can see this is the effect. And also I want to animate email address and password, but they should appear at different times. So I need to define two states, 14 email address and second one for password, and have these two different animations. So let's start by adding two new states. First one is show email. By default, this is going to be false. And second state is show password. By default, this is also false. And inside the enemy to use, we will have two new animations. So first one is for show email will change to true, then show password will change to true. And instead of ease in, we will specify is out animation. So ease out. And here we also have is out and we want to change the position. So I'll define another variable for offset. This is going to be CGFloat. And by default, before the animation starts, boat email address and password are going to be moved minus 200 to the left side. So for email field, we have offset that depends on show email. If show email is true, then there is no offset. Otherwise, we have X offset applied. Same thing for the password. If show password is equal to true, then there is no offset. Otherwise, we will have some offset before the animation kicks in. The final problem we have to solve is the animation sequencing. So we need to add different delays to email address, password, and login. Show email, it's going to have an additional delay of 0.30, 0, 0 point to show password is going to have additional delay of 0.4, and we will also add some additional delay to the show login animation. Let's say zero-point 86. And finally, we can add this 0.6 to the bottom as well, so that it appears after the email address and password are mostly done with changing the offset. Let's preview how this looks like. And you can see the animation starts by default. Both email address and password fields are visible. So we are going to apply the same technique by changing the opacity to, to, to these two elements. So for email field, I'm going to change capacity from 0 to one depending on show email. So if show email is equal to true, then it will have a capacity of one. Otherwise is 0. Same thing for show password. It depends on show password. If your password is true, then it's equal to one, otherwise 0. And now we finally fell this effect. Let's just preview how this looks like in the simulator. So I'll tap on the logging. And we have this animation for all our elements. 24. Create the Animated Wave Animation: And now the big animations finale, you are going to learn how to build these animated the bare ground. We're going to build this as reusable component. So you can just copy and paste this view and start using it straight away in your apps. In order to create the animated wave background. I'm going to start by creating our new reusable view. This is going to be new file, new Swift UI View. And here I'm going to name it unlimited wave. This animated way is going to have some initial parameters that we are going to pass to the animated way view in order to have it more customizable. So the first argument is going to be the wheat of our unlimited view. This is going to be CGFloat. Next, we need to have height starting point. This is going to be the top point of our and emitted we also, I'll add height ending point and have that as well as CGFloat. And I will define the wave amplitude. Also CG, float and give it a default value of Y 100 sold. Wave amplitude represents the height of our reef. And lastly, since we need to animate the animated, when I need to specify an animation duration. By default. It's going to be eight seconds, but we also can pass this as the parameter to customize the speed of our wave. Here we are missing arguments for we tight starting point and heart high to start ending point. I'm going to fix this by adding all those values. For wheat. I'm going to say use current UI screen bonds. Wheat for height starting point. I will say use your screen main bonds height. But divide that to do so that we start from the middle of our screen. And for height ending point, I'm going to select the point that is at the bottom of our screen. Okay, I can preview now this to see that I have the hill world and immediately delete these helloworld. Because what we really need is to define custom drawing. The way we can define a custom drawing two, drove our wave is by using PET. So PET takes one argument, which I will call PET, and now we need to start drawing our wave. The first thing I need to do is to move our pet to some kind of starting point. This starting point is going to be x of 0 and y, both height, height starting point. So this initial point where I will start with drying, it's going to be somewhere around here. So x of 0 and y of height starting point. So this is something like here, the middle of our screen. Next, I need to use this bet and AD curve. To our view. The first argument is the two CG point. This represents the ending point for our curve. In my case. This is the CG point of x represents the whole wheat of our screen, and y represents the height starting point. So we are, we are now drawing the curve from left side of the screen, from the middle of the screen to the right side of the screen. X is the whole wheat, the way that represents the wheat. And y is high, starting. This is the middle of the screen. We also have two control points. So with Control 1 and 2, we can define how we want this curve to look like. Let's add those CG points. So x, this is going to be wheat times 0 for 35. This means we are going to add first control points to the 1 third of our bet. So this is going to be somewhere around here. And for why we are still using height starting point. Starting point. But we also need to take into account the wave amplitude. So we need to add this wave amplitude to our CG point to make our first part of our wave. The second. Cg Point is similar. Bart here. We are using the two-thirds of the actual wheat. And for y position, we will subtract the wave amplitude so that we get this part of our wave. As you can see by default, the path automatically closes out. So it goes from this point to the bottom, to the top, goes to the destination. This is our two CG Point and automatically closes out so that it finishes at the start of our pet. We are going to add two new, two new points, two new lines. The first one is going to be line and that will go to the bottom of our view. Cg point for this is x of t and y of height ending point. So we made a line that goes to the bottom. And we need to fill out the rest of our shape. For that, I'm going to add a line to CG point. So we are going back the start of our left side of the screen. So x is 0 and y is height ending point. And this will create this custom palette and fill out the bottom of our view. Next, let's start animating this wave. I'm going to specify the offset. And this offset, we'll create the wave effect. In order to animate I have you. I also need to have our state, let's call it state private to our I animated. By default, this is going to be false. So if animated is equal to true, then I'm going to move it by the whole width of our view. Or otherwise, the offset is going to be 0. The final piece we need to specify is the animation modifier. This is going to be the linear animation that will also have the duration which are specified in the animation duration field. And we will also repeat this forever. So we have repeat forever and auto reverses is equal to false. Finally, let's trigger the animation by modifying the one up here, event callback. So here I'm going to specify that animated is equal to two. Now, if we resume this, hopefully this will animate. But I need to resume the preview. And you see we have this moving part. So what we're missing here is the second part of our shape that will appear before this first part of our wave hits again the screen. In order to fix that, I can add another curve and other similar curve to the previous curve I have defined. But here I need to specify the width. It's two times of the original wheat. So you see, we have this second part of our wave field. And these control points are going to be slightly modified as well. So we need to fill out the second part of our wave. It, That's why here, instead of zero-point 35, I am adding 1.35 here instead of 0.65. I'm adding the one-point 65 in order to feel the second amplitude of our wave. And lastly, these lines, this line that goes to the bottom of our screen, needs to be extended as well to cover the second part of our wave. And now we have the wave animation. One other thing that I've noticed during my testing is thus that this animated true needs to go inside this page Q dot main async. Since if I wrap and use these automated way view inside the navigation view, then the animation will drop from the top of the screen to the original position and we don't want that. And in order to fix that, I use this but q-dot main.out async. Hopefully this is going to be fixed soon so that we don't need to use the q-dot main ES6. But for now, I'm using this in order to make our work-around, around this navigation view issue. So lastly, what we can do is to specify the different foreground color for our wave. Let's have it blue. So I'll color that blue and specify the opacity of 0.3 to get this desired wave effect. 25. Create the Animated Wave Background: Now let's create the animated way for our password reset view. Our animated wave background for our password reset view will contain three animated wave views. So what I need to do is to create a new Silvio new file, Swift UI view. And name it animated wave background. Oops. Underrated with background. Instead of text hello world. I'm going to start by adding geometry reader view in order to get the screen size. So geometry in and in order to place three waves, one of two on the top of the other. I'm going to use the z's tech geometry reader. We are going to add another modifier to it called ignores safe elite area. All this, ignore safe area means that will be we will be extending geometry reader passed through safe area on the device. So safe area is this area around the top notch and at the bottom, here, at the bottom of the screen. So I can start adding my animated wave views. So animated wave. And I can specify we tight starting point and height ending, ending point. For wheat. I'm going to use geometry that size, that wheat. For height starting point, I can use geometry that size and that height divided by two. And for height ending point, I can define geometry dot size, dot height, divide without any division. This is going to create the wave to the second part of the screen. I can just push it a bit to the bottom. So, so that it takes less of half of the screen. Also, for this animated wave, I can specify the foreground color. It's going to be dot main, and specify a pest T of 0.3. Main color is the color I have in my assets. So this is the main color I'm using for my wave. This is the first wave. The second wave is going to be similar to this one. We are just going to specify a different opacity of 0.4. And also specify if the wave amplitude of 150 and animation duration of 12 seconds, seconds. So now we can see two different waves moving at different speed and have different wave amplitude. And lastly, let's add the third animated wave. So I can copy and paste the second animated wave and just change slightly the wave amplitude to 200. Also, animation duration to 10 seconds. Instead of color. That main, I'm going to use color dot Wave. These rhymes, so I know this is the correct core. And now if we automate this, we get these three different waves. For the third wave, I can, I can flatten the curve a little bit by adding the two times of wheat. So I will get this slightly bigger animation, the wave. Okay? And now once we have this animated wave background, we can go to the password reset view, embeds every, everything inside the VCE stack, including the stack in the stack, so that I can put one on top of the other. The first view.com in z stack is one and that will be shown on the bottom. And this is the automated wave background. And now I have this animated wave here. So I can just quickly go to the animated wave background and just change those weights slightly. So the second wave is going to have the weight of 0.2 so that we flatten him as well a little bit. And I think this is the desired outcome, at least in my case. So you can, if you decide to use animated wave, you can experiment with different wave amplitudes and animation duration in order to get desired effect for your app. 26. How to Use LazyGrids: For representing grids in Situ, we use lazy we agreed and release the age greed. Lazy we agreed stairs for lazy vertical grid. And lazy H greet stands for lazy horizontal grid. So let's start with screening implementation and then we will add the lazy. We agreed to the register type view. I'm going to start with the navigation view. Since I needed in order to navigate throughout the different register views. Besides the Navigation View, I'm going to add we stack. And inside the V stack, I'm going to add the reusable severe, cold screen title. And title is going to be, what are you looking for? Beneath the screen title comes our lazy V greed. It has some different options. So we can specify columns, alignment, spacing, pinned, use. And finally, content. Lazy big greed is called lazy because it supports lazy loading. So only views that are displayed on the current visible screen are being loaded. It's time for some ninja, isn't. There also? We stack and stack lazy variations called lazy we stack and lazy H deck. They're called lazy because they won't load the part of the view that is not currently visible on the screen. We stack and stack, load, all use inside them immediately. Let's go back to the lazy. We agreed. We need to specify the columns and four columns. I can define a new variable called grid columns. So this is an array that contains the columns we are going to have inside our greed. Every column is represented by greed item. And greed item has different options. So we can have fixed, fixed column. This is the column that has fixed width. There is also a flexible for flexible width. And finally, we have adapted adaptive, where items are lazy. We agreed, decide how many columns they need. I'm going to use flexible variant. And I don't need to specify minimum and maximum. Just going to define two columns. Too flexible combs. And now we can add grid columns here and start adding some content inside Lee, the lazy we agreed. For now, I'm just going to add a simple rectangle with frame of width of 150 and height of 150. I don't need the alignment. Let's just quickly copy and paste this. So you can see this how is laid out in the grid. You can see four rectangles. Let's just change the foreground color to blue. Foreground color of green, foreground color of red. And finally, foreground color of yellow. I have made it the different foreground colors for these four rectangles so that you can see the order of filling out this lazy we agreed. You need to have in mind the order in which items are populated in all ECV greed. The top row is populated first, as you can see by, we have populated first, blue, then green. And after that, the second row comes with red and yellow. To wrap up this explanation, exploration of the lazy way grid, let us just define the alignment. Let's say center. And we can also define the spacing option. I will put it as 24 so they are better aligned. If we change this to, let's say 50, you will see that the space between rows is changing. 27. Implement the RegisterTypeCard: Okay, instead of having these rectangles, as is, I would like to define our new subunits that I will use for register diaper option. Every rectangle, every card is going to have image and text below the image. So I will start with defining new struct called register five card. This is going to be view. And if we declare something as view, then we also need to define the body property. Inside the body property, I'm going to define the z stack. So we will have our rectangle, that is the background. And on the top of this rectangle, rectangle, we are going to have image and text. So we first start with the rectangle. And I would like to fill it with a gradient color. So in order to have gradient color feel, I need to specify two parameters for gradient. I need to have gradient. Star core. This is going to be color and also gradient and color. This is also color. While we're here. Let's define image that we want to put at the top of the rectangle. And also, let's specify card text. So now I can fill the rectangle with the linear gradient. Linear gradient requires gradient, start point and end point. Start point is leading. End point is going to be bottom. And S4 gradient. Instead of colour red, I'm going to put gradients, star color. And instead of color blue, I'm going to put gradient and color. So now instead of this rectangle, I can put register type cart and pass the parameters. Gradients, dark color is the custom color I have defined. And this is the room start. Gradient and color. For the first is room and color. Image is, I see. And card text is simply 0. Let's hit Resume to see the change. So we are missing some styling for register type guard. Let us define the frame of 150 by 150 alignment. I don't need this. And finally, I will add some corner radius of six to have smooth corners. So yeah, this looks more or less as it should look. The other two views I need to add. The first is image. For image. This is going to be resizable. Foreground color is going to be white. For frame. I'm going to have wheat of 60 and height of 60. And I will define a slight offset on the y-axis of minus 20 in order to move this image further up. Final piece of this register type card is the text. The text is car text's foreground color is going to be white. We can make it bold and offset. In my case, I'm going to move this text further down. So yeah, this is now the cart effect. I wanted to have. The final touch for this. The stack is still add some shadows and the radius of 10. I can now replace these rectangles, wheat register type guard, and have it four times. And I will have four different register type cards. The second card has image of IC. Then fireplace card text is entire place. And I'm just going to change the scholars. So this is blaze, start and end color is place. And the third one is, I see roommate. And the fourth one is by c then and weed card text of the month. But let me just change this color. So this is a roommate start, roommate end. And then I'll start. And then, and, and so by using this reusable type card, I can quickly build these customizable agreed items. I'll just quickly add some additional modifiers to the lazy way greed. So MUX week is going to be infinity. Let's also add some bedding. And finally, in order to add the title to our navigation view. So I can use negation dipole modifier. And say, this is step one out of four in user registration flow. For we stick, I can say it's frame has max height of infinity in order to make sure that the stack is fully stretched. This concludes the first resurrection view. Now I need to add another view, Swift UI view. And I will call this register place. You'll register a place for you. The user will choose which city he wants to find are the room or entire place. And we need to navigate from register type feel to register place for you. In order to navigate, I need to wrap up the whole z stack. We did the navigation link. So let's embed this with navigation link, destination, these resistor place view. And now we should be able to navigate to the next view. Let's reheat the resume and hit Play to see if this works. So yeah, this works. We can navigate to the register, place real. 28. How to Use EnvironmentObject and Navigate Programmatically: Before we move further with implementation of our registration of law, let's examine what we have. So now in our registration flow and how this works out for our end user. So user goes to the login screen, sees the sign-up button, ups on Sign Up button. It takes the place that he's looking for and goes to the register place view immediately. You can see that we have an issue here with navigation views. What's going on is that we are currently having to navigation views displayed inside the registration place view. 11. Navigation view comes from the login view. And the second one comes from the register type view. If we want to eliminate the navigation view that's coming from the login view. What we can do is to go to the end of our Navigation View. And here we can specify navigation bar hidden and set that to true. Now, if we take a look what we have. So it go to the step one, step two, and now the issue is gone. Okay? Next, what we have to do is to make sure that when we tap on, let's say, room or entire place or any other cards that we pass that information further through the registration flow. And once we come to the end of our registration flow, that we preserve that information and we know what kind of user do we need to register in order to pass an object through the hierarchy to the navigation view hierarchy, we can use the environment object in case you have some data that you want to pass to the view hierarchy. For example, when pushing new wheels to the navigation stack, like we have in the registration flow. Then you can use Environment Object property wrapper. In order to do so, you instantiate the environment object while you are creating the parent view. In our case, the parent view will be the first view that the user sees while, once he triggers the registration flow. And then that object will be available to all children views and all subjects. So let's see how to implement this. The first thing, what we need is our new model, that will be our environment object. So I will go to New File. Let's choose swift file. And I will call this user or boarding littles. This is going to be class called user onboarding details. And this user onboarding details class needs to inherit from the observable object or drawable object is our type of object that has some properties. And every time our property changes inside the observable object, then the event is passed to the view. And you can update itself with the new data that comes from the user onboarding details. In order to have this type of binding, we use published type of fields. So I will define couple of published fields. First one is going to be ruled time. So for our first registered type view, we need to store that in this room type, and this is a type of string. Also, I will specify three more, two more fields to more properties. Second one is location, initial value is empty. Third one is Move in date. Default value is just the date. And the fourth one is max rent. This is the type of double. So user will choose the max rent. He's ready to pay while registering to the app. Okay. We have our observable object, and now in order to use it, we need to pass that observable object as the environment object to our register type view. So we are going to the login view here where we have destination register type you. I will specify environment, object and create new instance of our user onboarding details. And now in register type you, I can go to the register type card and I should have access to environment. Object to the environment object property wrapper. I will call this onboarding details. And this is the type of user onboarding details. One note that you need to have in mind is that once you specify environment object in your views, then you also have to do this for the preview. So we need to also specify environment object here. In order for our preview to still works. Otherwise, the preview is going to crash every time. You want to resume the preview. Now we are ready to pass type of room we are looking for. So I want, once I tap on this cart, I will write the information about which card was stopped and then heat the navigation programmatically. In order to do that, I need another state that will say whether or not we are ready to navigate. And by default, navigate, it's going to be false. So navigation link will be triggered only if navigate is equal to two. In order to achieve that, we have is active parameter that we can pass. And we pass this as binding. I'll wrap the entire z stack inside the button and F4 button, I'm going to specify the action that once we tap on the button, we are doing two things. The first thing is that we are reaching for our on-boarding details and we are setting the room type to the current cards text. And the second thing we are doing is that we are changing the navigation to true so that we can trigger the navigation programmatically. Let's see how this works. So tap on the room. It triggers the navigation programmatically. Let's just make sure that we, once we get to the registration, please view that we actually have something written down in the room type. So I can go to register place View. And here defined the same environment object. So onboarding details environment object. I can copy and paste that. If I define that inside the view, I also need to define. For the preview. We can also try to preview what we have once we get to the register place view. So here on our peer, I will print the output of our on-boarding details and room type. So we are on the logging. Let's type of sign-up and room. And you will see that the room is being displayed. 29. Implement the RegisterPlaceView: In this lecture, we are going to finish the implementation of our register place feel. So we have added the environment object for our user, of our user onboarding detail, Storage sur place view. But if we tried to build and run, it should be fine. Now, here we will also have agreed with four cards similar to the register type view. And each card will represent the city that the user can top and choose. So what we will do is define the same flexible grid columns here. And now instead of this text, I can start with the implementation by defining the V stack. Inside, though we stick the first thing on the top, it's going to be screen title. And the title is going to ask the user, where are you going? Next thing, what we have is lazy. We agreed wheat columns. As agreed columns. The Alignment is going to be not that center. We will have spacing of 20. Here. For lazy, greedy items, I need to define our new card. I will call this cart register location cards. So this is going to be filed private struct called register location cart. And this is going to be the view as well. So if we have view, then you know, what we need to do next is define the body of our view. We will also need this environment object to store which city has, the user has, has choose for his destination. And we will also need to have the state to indicate when should we navigate to the next view in our flow. So navigate is equal to false by default. And inside the body, I will start by adding the navigation link. The destination. For our navigation link is going to be another view called register move details to you. So what are you going to do is to add new file, new Swift UI file called register move details view. So while we're here, let's go and add another view for the final piece in our registration flow. And that is going to be called register profile view. Okay, great. Let's go back to the register place view. And now we have our destination. That's register move details. You. This negation is going to be triggered only after we change the state of our navigate field. And inside the navigation view, I'm going to have the bottom left. We have the action of setting the onboarding details and end location to the card text to the city that we provide. So let's go and defined all the pieces we need for our cards to be initialized. We need image, we will need the city, and we will need country. So for location, we will select the city. And after that, change the navigate the state to true. For the actual content of our button. Here, I will define the restock that will have the allele alignment dot leaving. And implement the cart around inside this we stack. So we will have image at the top and at the bottom of the card, we are going to have to text. The first one is city, and after that comes country. So let's do that right now. So for, for image, we are going to pass the image after dot-coms text for Citi. Let's just customize this text a little bit. We'll have foreground color of title. So this is the custom color we have defined. And we will have this text as bolt. Just below this text columns. The text for country font is going to be System font. And the size is going to be custom size of 14. And for foreground color, this is going to be text. Great. Now we have our cart. Let's just put those cards in inside the lazy V greed. So register, location card. It has three fields that we need to feel. First one is image. This is the IMG. London. The name of the city is London, and country is UK. I can hit the Preview to see how this looks like on the actual screen. Okay, great. We just need three more cards and we are done. The second card is for for Paris. So image is IMG, Paris, city is Paris, and country is France. The third one is for New York. Saw image. New York. City is New York, and country is USA. And finally, we have image. Boston, CT is Boston, and country is USA. Okay, let's get the privilege to see if this works. So we are missing the Navigation View inside the registration place for you. That's why we cannot navigate to register, move details. But if we go to the register type, you will see that we are hitting the third view, and this is the register move details. 30. Slider Control: In this lecture, you are going, you are going to build the top part of the register, move details view, and get yourself familiar with the slider control. Let's start by removing the Hello World text. And instead of hello world, I'm going to create a new stack and add the alignment of bleeding. The first component inside the register movie tells you is the screen title and the text is, what is your maximum rent. So below the screen title, I'm going to put the slider control. So new, we stack. And here I'm going to define the slider. The slider has different initialize, various, different initializer. I'm going to use an initializer with value in and step. Without the on editing changes. For slider radio, we need to define our state. Solids, find state, private, var max, rent. But instead of defining state, what we could also do is store defined the environment object, our user onboarding details, and store that directly the current slider value. So Environment object var onboarding details, and this is declared, this is the class user onboarding details. And now I can directly bind to the environment object. So onboarding details, max rent in means the values Min and max value we have inside the slider. Minimum value is 0 and maximum value is 5000. And finally step, so I want to slide in steps of 100. Let's try to build this. And I can add to preview this file because I am missing the setup of environment object of our user onboarding details inside a preview. And immediately after I said this, I get the slider. And I can interact with in order to show slider radius, I can define our new age stack. And inside this age Doc, I can define label. That is, I can define the text that it's going to show the slider value. So for the alignment. I will define bottom alignment. And here I am going to define a text for MC, for displaying max trained. But this text is going to be formatted. So I will define power format to display this number without decimal point. So this is the format for displaying without decimal points. And here what I'm displaying are the on boarding details dot max rent. And I get this value. If I change the slider, this value is automatically updated. I can just quickly make some changes to this text to customize it a bit, little bit. Foreground color is blue. I will make it bold. And font is title. And another text that will come immediately after my slider value, after my present value is per month. I will just sum, add some bottom. Think of six and add some leading bedding of 20. Next, let's finish this by styling the slider for further. So I want to add some padding on horizontal axis. And beneath the slider show what's the minimum value, what's the maximum volume? First, let's define horizontal padding of 20. And also I will add bottom padding of 40. And finally, here I will define the eight sec. It will have two texts. First text is representing 000 dollars and foreground color is dot text. I will add the spacer in order to create our new text with a value of 5 1000 doors. And also apply the same text, costume, foreground color. And now we get this display beneath the slider. What's the minimum value? What's the maximum value? 31. DatePicker Control: In this lecture, I'm going to show you how to work with the date picker control. Let's continue with implementation of our register. More details view by adding another screen title. This screen title, we'll ask when is your Moving date? And below this, we will display date picker. And as for the slider, date picker also has different options to initialize the date picker. I'm going to select the option that has Selection, display components, and label. For selection. I can as well. Bind this to our environment object on boarding details to the moving dates. Published property. For display components, we can choose different date, time components that we want to show. In my case, I just want to show the date. And finally, for our label. So this is the decks that it's displayed before the date picker. And here I'm going to display text that says Moving date. So immediately you see this date picker control. Let's just quickly add some padding, horizontal of 20. And if we resume our preview, you will see this pop-up style of our date picker. So change the default date picker style by applying the date picker style modifier. Here, you can select, we'll date picker style to have this different. Because style also, we can change this to graphical date picker style to get this kind of date. And there are also some other styles. You can explore them if you want further. One final tip is that you can also remove this Moving date label by say, labels hidden. And this will eliminate these labels. 32. Finish RegisterMoveDetailsView: Okay, we're almost done with our register. More details feel. The final piece we need to add is the button at the bottom of our view to say is next, so that we can move to the final view in our user registration flow. I will start by extracting these into separate sub u and just to clean up the code a little bit. But since I don't have the option to extract to solve, you will then need to do is first to embed this investor deck. And after I embed this in V stick, then I can extract this subview. I will call this sub you rent details and also I'm missing the environment object. In my rent details. I will define it as file private. Okay, let's hit Resume. Everything builds, so that's fine. Let's just quickly add some styling. So I will add padding at the top of 40, put spacer after our rent details, and finish this by adding the navigation link. Destination for. For our navigation link is register, profile you. And the label for our navigation link, He's text that has value of. Next. Let's just apply the our Gradient button text style. And I will quickly add some bottom padding of 20. Okay, let's preview what we have so far. So we start with our register type View. Go to the next step to see what place do we want to choose four, our room search. Here, we are missing a title, navigation title for our second step. So let me just quickly fix that by adding the navigation navigation title of step two out of four. And let's preview again. So first step, second step, okay, now we have this navigation title. We select our maximum rent that we are willing to pay. Also choose the Moving date, hit next, and we get to the register profile view. So we're also missing the navigation title for our register move details. I can specify navigation title of step three out of four. Let's just quickly preview this again. First, second, third, next. Yeah, we have this navigation title now and our registered profile view is next. 33. Picker Control: In this lecture, we will start with the complete your profile that is registered profile view. And we will start by wrapping everything inside the ScrollView. So I'm going to show you how to use the scroll view in Swift UI. And after that, we will add text fields for full name, phone number. And lastly, you will see how to work with the beaker control. So now I'm in the register profile view. And the register profile view is empty. And in order to scroll the content inside the view, we use the scroll view. Inside the scroll view, I am going to define a new stack and add some spacing of 16 to have the equal space between all components inside the register profile view. So I will need three states for full name, phone number, and beaker, so forth. Full name. I'm going to define full name, state, and initial value is just empty string for phone number. So same thing. Again. This is going to be empty string. And finally, the state for our beaker, I'm going to call it select and gender and defined. And default value is 0. So we will get the selected index of our gender beaker. Let's start with the first text field. This is the text field for the full name. The place holder is full name, and the text is going to be stored in the full name state. We will disable the auto correction for our full name. And also for the TextField style. I'm going to choose rounded border, fixed feel style in order to get borders around my text field. Okay, I will need some padding around the VCE Tech to get a bit of space. And I can continue with building the phone number text field. So this is our again text field that has placeholder of phone number. The text is going to be stored in the four number state. Also, I will disable auto correction. Keyboard type. I'm going to set to foam pad in order to get the correct keywords type for entering phone numbers. And here as well, I'm going to use text fields styled of rounded border, text field staff. Finally, let's build the beaker control for selecting the gender. I will start with defining the stack inside the mistake, which has the alignment. Know if dot leaving at the top. And just above the picker, I'm going to define the label that's going to be displayed for the beaker. The text for this is gender. Foreground color. Foreground color is text. And finally, in order to use beaker, inside Swift UI, we select the bigger view. Also has multiple options. So for selection, I'm going to save this selection into selected gender. I can also define the label for our picker. This is going to be simply text that has label of gender. And the final piece that we're missing are some items that the beaker will consist of. So I will use for each loop through the gender count and loop through the array called gender that we currently don't have solid me. Just define the array for genders. And it will have three options. The first one is male, the second one is female, and the third option is other. So I will loop through this array and display every element as text. So I can get the every gender item by passing the index and using this index to select the appropriate text of gender. Lastly, we need to talk this text to get the selected value back to the beaker. This is going to be just simply index. And now if we try to build this, I get some errors. So here, brackets are extra arginine, these brackets. Let's try again. And by default I get these will occur. If I want to change the picker style. What I can do is to go to the pygostyle modifier. And here, instead of this, we'll style. I can select segmented beaker style. And this will change the beaker to this segment bigger. Also, I can style the peaker a little bit by specifying the background. Here. I will use color called beaker, foreground and some corner radius of eight to get smooth corners around my bigger. And now I have the desired effect. 34. TextEditor Control: The next elements in our register profile views are elements for entering e-mail address, password, and confirm password. Since you all should be more or less familiar with e-mail address and password fields. By now, I'm going to fast-forward this. And once I come back, I'll then show you how to create and use the text editor view in Swift UI. Hi, and we're back. So nothing fancy here for email password and confirm password, I've created three new states and use them for TextField for displaying email. I have added some properties to the text field to disable auto correction, to set the keyboard type, and to set the auto capitalization to none. And created secure field for a password and secure field for confirm password. Finally, I have added the navigation title to complete your profile. The final piece that we're missing is editor, where the user can enter more information about the self. And this is in form of free text of description that can span across multiple lines. Text editor control is a control that was introduced at iOS 14. And first version of CF2, I was missing badly this type of view. And there are a lot of workarounds needed in order to display multi-line text editor inside the swift UI. So for our text editor, I will create, we stack to embed this text editor and another text, and that will be the label for our text editor. So the alignment of our stack is going to be leading. The text. Above the text editor is going to be, Tell me more about you. V8, foreground color of text. And here I can define the new control text editor that has only one override. And this is the binding for text. So in order to bind this, I need another state for more about you. And I will bind this to this text. If we resume our preview. Here, we should have the text editor currently, it's not very visible. So what we can do is to style it a little bit and select the frame. The frame height is going to be 100s and alignment is going to be top, leaving. Let us just also disable auto correction here at some padding of eight. And I will add the overlay, the border around our text view. This is going to be rounded rectangle that will have corner radius of six. So immediately you can see our text editor and the overlay of our rounded rectangle. And less defined the stroke for our rectangle. So this is going to be color gray with opacity of 0.3. And the line width for our stroke is one. So now here you can see this text editor. And this text editor can have multiple lines. The final piece in our register profile view is the register button. This is going to be the navigation link that's going to, in case of successful registration, navigate to our home view. So we are missing an under modules called home. Let's create a new group called Home. And here I will create a new file, new file called Home you. And instead of hello world, I'm going to say hello home. And for register profile view, you already know the drill. So destination is our new home view. For label. We can specify text, that's going to say register. And text style of Gradient, button style. Great. We have our button, but the bedding on horizontal axis is a bit too large. So I can add the horizontal padding of minus 20 in order to make the button a bit bigger. Also, I will add the padding. At the bottom. 35. How to Hide Keyboard: So far we have created register profile view, and we have this form where the user enters full name, phone number. You can choose gender. It gets select email because it's input passwords. And also it can select, tell me more about you and type the description. The one problem we have here is that we are unable to hide these keyboard, for instance, when we tap outside of the text editor. So let me show you how you can hide the keyboard. Once you tap outside of the text fields. For that, I'm going to create a new extension. So new file, new swift file. Next, and call this view extensions. Here. I'm going to create an extension of view and create one new function that we'll say height. Keyboard. This is going to be just simple function that once we top on our view and we will call this hide keyboards function and we should be able to hide the keyboard. So instead of import foundation, I need to import Swift UI. And here I will call UI application that shared sent action. So selector for our action is UIResponder that resign first responder to Neil from you can also specify this. Neil and went. You can specify this as Neal as well. And now it should be easy to use this function. Let us go to the herd STR profile view. And here I'm going to select the top gesture for our V stack. And here I will call height keyboard. Now it up through our fields. So when we get to the tell me more about you and we can type something. And when we tap outside of the view, then the keyboard gets hidden. We can also take this one step further by defining the on commit action for our text fields. And here I can call the height keyboard as well. So once I run the app again, times something in the full hit return, and the keyboard will be dismissed. 36. How to Refactor Views: If you take a look at the register profile view and scroll down a little bit, you'll see that we have a lot of code inside one place. Ideally, what we would like to do is to have smaller chunks of code so that we can easier find the particular area that we need to change in the future. Another way to extract parts of our view into separate components is by, is by using the Extract Method refactoring. This is pretty simple. In Swift UI. Basically, what you would like to do is to take those text fields and put these views inside separate functions. Let me show you how to do that. So select the text field you want to extract. He'll command control. To get all the available action. Here at the bottom, you have extracted to method. And now I can extract this code and name this full name text field. I can also move these modifiers inside this function. So this function returns TextField of text. I can change this so that it returns some u and now the errors will disappear. Let me also format this code a little bit. And one called shrieking Swift. So if you just have a single return statement, you can remove that and just have text field. We can continue and refactor the rest of the fields. So I am going to apply the same method to all these fields. So now if you take a look at our register value, you will see that he has a lot cleaner code here. And we have specified the function's width names that identify what we are having inside those methods. So we have full name for number, gender, picker, e-mail address, password, confirm password. More about JU text editor, Register button. And if we command click on this function, I go to this code and I can change this code freely. 37. Navigation With ZStack: To wrap up this section, let me show you how we can use z stack in order to perform navigation from one view to another. So I'm inside the onboarding view and I have this Get Started button or the moment we have no action defined for our Get Started button. But I would like to, once the user taps on the Get Started button, I would like to navigate to the register type view. So what we can do is to define the z stack. And then once the user taps on the Get Started button, we can show the register type view. Let me show you how to do that. So I will go to the main we stack and embed that in the z stack. I also need another state. I will call show register. And by default, we don't want to show register. But once we tap on the Get Started button, we want to toggle the show register to true and inside the z stack. So I will go to the end of our stack. So that's here. Now we'll just comment that this is the end of the race stack. This is the end of z stack. And here I can define our if condition. So we want to show register. Then what we can do is to type register, type view with the environment object, which will be user onboarding details. This means that once show register is changed to true, that register type, you will be the topmost presented to you in our Z stack. So if we resume our preview and now top on the Get Started button, we will get the register type view. 38. What Is MVVM : Before we go further, let me explain you. What is the MVVM pattern and what are some benefits of using the MVVM? Mvvm stands for Model View, ViewModel. In this image, you can see how the architecture looks like. The view is responsible for defining the UI layout of what the user sees on the screen. Each view is defined with Swift UI views. The ViewModel implements properties and functions to which the viewer can bind to and notifies the view of any state change through bindings. Do you model is also responsible for coordinating the views, interactions with any model classes that are required. And lastly, we have the model layer model. There are usually the structs that hold data. Viewmodel is responsible for updating models directly or indirectly through other types. Typically, we can have services. You may ask, how are these layer organized? At the high level? The view knows about the ViewModel, and the ViewModel knows about the model, but the model is unaware of the ViewModel. And the ViewModel is unaware of the view. Therefore, the ViewModel isolates the view from the model and allows the model to evolve independently of the view. What are some benefits of using MVVM? First, it is possible to write unit tests for the ViewModel and the model without using the view layer. The unit tests for the ViewModel can checked the exact same functionality which is used by the view. Next, the UI part can be redesigned without touching the business logic. Therefore, our new version of the view should work with the existing ViewModel. And finally, with MVVM, you avoid the MVP pattern. In this case, NVP stands for massive views pattern. Instead of having everything inside one file in CATI, that's usually the view. You split layout from the business logic. That way, it's easier to manage smaller files. 39. Connect View and ViewModel: Okay, let's start by creating our first ViewModel inside our Stacy. Yep. The first few model I'm going to create is for password reset to you. So if you remember, this Forgot Password view is relatively simple. The user just enters the email address and the request is sent to his email with the password reset instructions. Once the user taps on got it, it navigates back to the login screen. So with our ViewModel, we want to put the part of this logic to the ViewModel saw we will store the email address to the remodel. And also we will trigger the showing of alert inside of your model. So only after we actually sent the e-mail with password reset instructions, we want to show this alert. In the next section that covers Firebase, you will see how to actually implement this functionality. You will see that by using Firebase, this functionality is pretty simple to implement. To send email with password reset instructions. Okay, so we can select the password reset new file. I'm going to create a new swift file and call this password reset view model. This is going to be class password reset your model. And one other important thing is that our view models implement the observable object protocol. We need to do that in order to publish any changes from our password reset your model to the password reset view. So here I will define two new fields. First published field is going to be for storing email, and the second one is going to be for showing alert. So instead of having these two fields inside the password reset view, now what we are doing is moving these two parts to the password reset view model so that we don't add this part of business logic to our views. I can eliminate these two states. And instead of having these states, I'm going to define the state object. That will be our ViewModel. State object property wrapper represents the type of class we are storing within the view in such way that once the view refreshes, the state object will stay the same. That is, all the changes preserved inside state object won't be reset to initial values. So now, if we scroll down, we see that we have this showing alert. And instead of using showing alert, which was state, now we are using password reset view model and showing alert. Also. We have email field binding here. For that, I use the email field. And finally, action. Here, I want to define a new function inside the password reset, new model for sending the password reset. Funk, send the password reset. And here we will change showing alert to through. The final piece we are missing is the actual logic for setting for sending the password reset instructions. For that, I'm going to create our new service. So let me create new services folder. And here I'll create a new file called authentication service or just out service. The purpose of the out service struct is to hold all necessary business logic for authentication user. So here we will store the business logic for sending a password reset instructions, also registering new users, and also the logic for providing the login for our app. So as you can see, I am further separating the business logic in such way that we are only having one type which is responsible for the whole authentication process. And in this way, we are eliminating all this logic from the password reset view model. And we did that password reset model stays smaller and it's only responsible for changing these published properties, which view binds to. Our struct authentication service will have several functions. The actual implementation of this function will come in the next section, where we cower Firebase because we will use Firebase to implement the authentication for our application. But here, I can define several of function that we will need to implement in the next section. The first one is function to get the current, current user of our application. So we will need the user class for this. So I can immediately create a new, a new class for this user. So let's go to models. New file, Swift UI file. The class is user. This will, this class will contain all information that we are storing about our currently current user, which is using the application. So class user. And for now, let's just store the e-mail. All our fields I'm going to define later. So we're missing the initializer here. Let's just create a quick initializer. So email, string and self.age, email is equal to email. Okay, back to defining our authentication service and its functions. Current user, this is going to return optional user. Since we have user which is currently using the app, because user has not been registered or logged into the app. The next function is going to be for providing the login functionality. I will call this function login user and define email that we will use to login. The user. Also. I need password. And finally, we will have the completion block. This completion block will be a closure that will return the error. If there is any error produced while logging in the user end, there won't be any return type. Next, I will have the function to send password reset instructions. For that, we need e-mail. And here as well, I'm going to have the completion block with escaping closure. That doesn't take any arguments and returns void. And finally, one more function I'm going to define here is for registering user. So register our user. And there is completion block that as well. So the same completion block as with the login, we might have some kind of error which occurs during registering a new user, but This is optional and there is also no return type with this completion block. Okay, I'm going to just put some comments that we need to implement this with Firebase. So cent password, login, user, register, user, this will all be covered with password. For now, I can just have some dummy implementation that we'll just call the completion block. Let's see how to use authentication service inside password reset view model. So this should be pretty simple. I will just define private authentication service and here called the password reset function. So send password reset with e-mail. So the e-mail we are providing is this one which will come from our password reset view. And as for our completion, I can just put this showing alert beside this completion block. So we need to use self and I will capture the self here. Now, if we preview our changes, we see that we have one more error. So instead of showing colored dot toggle, I'm using now password reset view model to send password reset. And if we resume our preview and try to send the request, now, we see that from the user's perspective, nothing has changed. So the user centric user send request again triggers the alert. But now we are going through the password reset view model and password reset. It's calling the authentication service, which we'll call Firebase. And after that function is completed, we will change the showing alert back to two. 40. How to Navigate Programmatically in MVVM: In this lecture, I'm going to show you how to navigate programmatically, programmatically in MVVM. So there is a common scenario where we have login view. So I can switch to a log of u. So we have our Login view and the user enters email address, enters passwords, tops login. And after the user taps login, what we want to do is to authenticate the user based on email and password. And if authentication is fine, then we want to transition to the next view. Let me show you how to do that in MVVM. The first thing we need is to create a new file, new swift file. And I will call this file login view model. Okay? So this is the class login with your model. This is the observable object. And you will have published properties for email and password. Instead of using email and password as states inside the login view. So we can move that to login your model. And instead of having states, we are having published property preppers. Also, I need to define the third property. And this property will control when we are transitioning to another view. I will call this property login successful. This is the Boolean property and by default, login successful is set to false. Here. I can also define and use our authentication service. Again, our authentication service will control and hold all logic for authentication, authenticating the user through our, our app. Let me just define one function called login user. And inside this function, we want to do two things. So we want to call authentication service and its login user function. We will pass the email, we will pass the password. And here we have the completion closure. The completion takes error, which is optional error. For now, we will skip the whole error checking. And just here, I will set. Login successful to true. So we have to do here to check error and show alert. If there are errors. Again, once we implement our authentication service in the next section, which will cover Firebase, we will have the proper errors coming and we will implement the error checking and handling. And now if we go to the login view, again, now we'll define state object for our ViewModel. This is going to be the login view model. And use login view model is said our states, which we have moved to Logan ViewModel. Here, I need to define binding to e-mail. And here I need to define binding tuple password. So we are using dollar sign, Though represent the binding. And finally, our login button action. We will do two things for Inc.. In case there is a keyboard presented, we want to hide the keyboard. And second, more importantly, we want to call the login user function. So this function is going to call the authentication service and set login successful to true. Once login successful is true, then we can navigate to the next view. Next few after the login is the home view. So what I can do is to use the stack to show the home. So again, I will embed everything in z stack. So here is the end of the stack, here is the end of our Navigation View. And here I can say if Login view model dot login successful is equal to true, then I can show the home view here. Let's resume and see the desired effect. Okay? So tap on Login doesn't produce anything. And that's probably because I have forgot to call the completion inside my login user. So completion, and for now we will pass nil. And now if we go back to our Login view and resume the preview, you'll see this hello comb. This hello home actually comes from the home you, in case you want to have a whole view with the white background so we can use color. Primary ignores safe area. All. But primary color is the black coral color in our white appearance. So what we can do is to use color invert modifier to change the primary from black to white. And now if we go to our Login view and tap login, you will see this hello home view. 41. Create RegisterViewModel: Okay, Our register profile view is next. So I need to create our new ViewModel for our register profile view. This is going to be new swift file, and this is going to be register. We'll model. Great. So this is the class named register. We will model. And this is the observable object. Now what we need to do is to move all these fields to the register view model. Okay? And instead of state, what I need to have here is the published property wrapper. I want to change multiple lines and at once. In order to do that, I can control, I can select option and drag to the bottom. And now I can edit multiple lines. Okay, so we don't have the state here. But now we need to use register ViewModel. And you are to use register ViewModel. We need to define new state object. Let's call it register. We'll model. This is the instance of register view model. Okay? And now I should prefix all these properties with two register ViewModel. So I'll register your model dot full name. We have register ViewModel, phone number. Next, we have the selected gender. Here. We use register ViewModel from the end, gender array from the register ViewModel, E-mail, password and confirm password, and more about TO. So if we try to build now, everything should be fine. Okay, great. Now what we need to do is to take all these fields and also define them inside our user model because we will need to initialize the user with all those properties. So here I'll do the same trick. So Option and drag to the bottom. Option and drag to the bottom. And instead of published var, I will define everything as LET. And also I need to remove all these default values. So with this simple shortcut, you can modify multiple properties at once. Okay, So are missing the type for our fields. So full name is string, phone number. It's also going to be stored as string. Select them gender. This can also be string. Email is string, password, string, confirm password. String anymore, about two. This is the string as well. I have one email field extra, so I can remove that. Next thing. The compiler is complaining that I'm initializing a new user, but I don't have all fields populated. So what I need to do is to populate the user all these required fields. Okay? I have created the initializer for this and populated all required fields. And one last thing Could I did is just renamed cycle gender to gender to better reflect the property of a user. 42. Validate User Input: In this lecture, we'll continue with our user registration functionality. I am going to show you how to create a new struct called user validator. In order to validate the user information we want to register the user with. If we continue with our implementation of register, you model what we need now is new, new function that will be named simply register. So once we tap on the register button, we will trigger the registration flow. Here. Inside the register. You will create new user with all this published fields we have collected so far. So I'm going to create a new user and fill all these fields. So email, I have full name, phone number, gender, password, confirm password, and more about to have one error here. So I need to use gender array. And by using these laid tilde gender index and get the actual stink. Before we actually sent the, all this user information to the Firebase, to the authentication service. The first thing, what we need to do is to validate that the user has populated all these fields. And if any of these fields is empty, then we will show the error to the user that he needs to check these fields and populate them. If any of these is not populated. Usually for validation logic, we can create our new struct called user validator. So I'm going to create a new group called validators. And here I'm going to create a new file, swift file, excuse me, swift file user validator. Here I'm going to define a struct called user validator. And user auditor just has one function, is valid user and this is the type of user, and this returns a bool, whether or not the user is valid. So by default I can return true. And here, above this, I will have the logic to check whether or not the user is what. So one note here is that we could also store this is valid function inside the register view model. But again, in case we ever, ever, ever want to reuse this logic, then we can simply create a new instance of user validator and use this is volume function. And the second argument for using separate type for validation is that we are adhering. The single responsible principle. This principle says that the class or struct should have only one responsibility. In our case, register ViewModel is responsible for providing data and bindings to the register, profile view, and user validator. It, it also has only one function. And that function is to check whether or not a user is volatile. So I can now go and check every single field inside user. So we need to have a guard. That user.email. E-mail is not empty. In case the user email is empty, we will simply return false. So we are using the guard close in order to check whether or not user email is empty. And if the email is empty, we are returning false. We can use those same principle to take all other fields. So I can check whether or not full name is empty, then phone number, then password. And finally, confirm password. There is also a field called more about you. But this field, I choose to be optional. The user can choose not to enter any additional information about himself. So we are now ready to use this user validator inside our register ViewModel. I can define user validator here and use it in our register function. Let's find an if condition to check whether or not user is valid. So if our user while later that is valid, the user we have just created. Here, we want to set two properties. First property is for raising the Boolean value that the error has occurred. So by default, this is going to be false. But here we will set error occurred equal to true. And we will also provide our custom message to the user in form of a new alert view. And we will call this register error. So by default, this is the empty string. But here we will set the register arrow to some fields are not correct. Please check. And we will return from this. Function. If everything is fine, then here we will have to do register user. Great. We now have all required logic defined in register of your model to go to the register profile you and implement the UI part of this register profile validation. So I have defined previously register ViewModel. And now inside my Register button, you can see that currently I'm using navigational link for the register functionality. So while they need to do is to embed this text inside the button and specify the action for the button to actually call register ViewModel, not register. So this will trigger the validation of our information. And in case if there is any kind of error, we want to show the alert. Here at the end of our stack, I can define the new alert is presented, is controlled by a register. Model and error occurred. Binding inside the alert. We need to define a new alert by using alert view title. This is going to be text that will set error. Next. We will define our custom message for our alert and we will get the texts from register ViewModel that register error. The final piece we are missing is inside our navigation link. We are navigating to destination. But we want to control programmatically. When should we navigate to the Home view? So I need a new binding for is active and I will also define that inside register ViewModel. Here. I will define new published var registration. Successful. And this is going to be false. If our user is valid, then we want to register our user and set our register successful to true. Okay, Let's go back to the navigation link. I will call register remodel dot registration, successful. So only if registration is successful, we want to navigate to the home view. And now if we check our register profile view, if all fields are empty and we tap on Register button, we will get the error that some fields are not correct. Please check. And if we populate all field and top on register, then we can go to the Home view. 43. Introduction to Lottie Animations, Swift Package Manager: To the reminder of this section, we are going to build this loading pop-up. So we will use Lottie animations in order to build this animated image and put it inside the pop-up, you'll also see how to use UIKit views inside the swift UI. Let's start with introduction to Lottie. What the is a library for Android and iOS that enables you to have animated images inside your mobile application. The animation files are usually provided in JSON format, so they are extremely small in size, but can be really complex. We are going to go through the installation instructions for the latae. We can use different types of installation. We can use GitHub, repo, CocoaPods, cartilage, or Swift package manager. I am going to use the option for Swift package manager. So you've Package Manager is a management tool built in the Xcode, and I'm going to show you how to use it in order to import the Lottie library. It's really simple. We just need to follow these four steps. And then we will be ready to use Lottie inside the project. In case you are wondering, where can I get the free latae files and animations? You can hit over to lots of files.com. And here you have a big open source library of Lottie files. And you can see there are different animations. There are also some paid options in case you want to go premium place where you can find is shape. So I am going to use one motif file from shape dot ISO and show you how to work with that. The first thing we need to do is to add the Lottie library to our project. In order to do that, I go to File Swift packages at package dependency. Here, I paste the URL of the latae provided on the GitHub repository. And click Next. The rules are for this repository that we will stick to up to next major version, meaning that the dispersion of library will be updated up to next version, which is 4. Since major version sometimes can break things, we are preventing that by upgrading up to that major version. Again, I will click Next. And this whole fetch, the latae for iOS. Target is Stacy demo. This is fine. And let's click on Finish. At the bottom of our navigator. You can see that we have new Swift package dependency for Lottie. The final thing we need to do according to this instruction is to set that code stripping to know in our Build Settings. So Build Settings, I'm going to paste that code stripping all and set this to no. Let me just build the project to make sure everything is still fine. 44. Show UIKit Controls in SwiftUI: Great. Now I'm ready to create our new view. So I will go to a reusable views new file and create new Swift UI view. Hit Next. Here. I'll create latae view. For now, I'm going to remove the canvas area. And here for our lot of you, instead of using view protocol, I'm going to use UIView representable. We are using UIView representable in cases when we want to import parts of UI Kit functionality to the swift UI. In order to implement UI view representable, we need to have two functions. So first function is make UIView. And we need to specify the context. Context is UIView representable context. And here we are providing the latae view. The second function we need to have is update UI View. And here as well, we will use UIView representable latae you. This of the update UI view is for updating our UIView and we won't need this, but we need to implement make UI view. In order to implement this make you a view, I'm going to create a new UIView here and set frame to 0. Let me just return that so that I remove all compiler warnings. And here I need to specify our new view. This is going to be new Animation View. Animation View comes from the latae. So I need to import latae as well. And now the animation view is available inside. You will just specify some options. So for our multi-view, what we want to have is one argument for initializing the, a lot of you. And this is going to be an animation name. Let's have it as a string. I'm also going to remove the preview and preview this inside another view. So we need to provide some options for our animation view. The first thing we need is the animation itself. This is the animation named animation name. Our animation view has the animation we have specified in the line above. So this is the animation. Let's specify the content mold. This is going to be scale Aspect Fit. Also. We want to loop this animation the whole time. So I'll set the loop mode to loop. But you can also specify the option to just play once this animation. And I need to start this animation. Let's just add some final touches to our animation view. The first one is translates auto resizing mask into constraints equals to false. Now we are ready to add subview to our view that we are returning from our UIView. This is going to be animation reel and final tick list, fix the layouts for our animation view. So I'm going to activate some layouts. The first layout, it's for wheat. So animation that with anchor, add constraint. It's equal to view width anchor. And I don't need the multiplier. The second constraint is for height anchor. I will have the constraint equal to view. Height anchor as well. I don't need the multiplier here. Great. We have our lot of you now and what we can do is to create our loading view. So inside, I'm going to create a new file, new Swift UI file called loading view. Let's create that. And in order to use our log file, I need to also specify the latae animation file. I have my phone dot JSON file, and I can drag and drop it to the project, copy items if needed, set to true and click finish. Because of commercial license, I'm not allowed to share this phone JSON with you. But what you can do in case you are follow along by coding. You can go to lots of files.com. Select the file, not the animation you find interesting, and simply download the JSON file. You just need to register and you'll be ready to download this animation for free. So we can now show the Canvas. And here instead of text Hello World, we can include lots of you with animation. My name is equal to my JSON file, and this is form. Let's just set the frame of width and height to 60 by 60 and preview what we have. Great. The animation is here. We just now need to finish the rest of our loading pop-up. 45. Implement Loading Popup: Finally, we are ready to implement our loading view, which contains the latae view. So I will have this lots of you and above this latte view, I want to put on other texts, which will said almost there. So I start by wrapping everything in, we stack and above lot of you, I put the text almost there. Now, I can quickly style this text. Form title is fine. Let's make it bold at some padding around it. And I will change the opacity from 0 to one with the animation. In order to animate this, I need another state. Let's call it state var show is equal to false. And based on this show state, which should be private, I am going to animate the opacity from 0 to one. This is going to be animated on up here of our restock. And here, I will toggle the show from false to true. The final piece for animation is to add the animation modifier. So let's define linear animation with the duration of one, but just add the slight delay of 0.2 seconds. If we resume the preview and hit Play. So we get this on a pair of positive change from 0 to 1. Great. I can copy and paste the same effect for our lot of you. Here. I will just add slight bigger delay to 0.3. So when we hit on play, the boat, views appear. Next. Let's add the background for our pop-up. So by using backgrounds, modifier can specify color. That main, add opacity of 0.8 and style it a little bit by using corner radius of 30 and add shadow. So for shadow, we are going to use color black dot opacity of Zero-point 85, radius is 30, x of 0, y of 30. We can move this view slightly to the top by specifying the offset of, let's say, minus 50 to have it a little bit moved to the top. And also, I'm going to animate the scale effect based on our show state. I'm going to scale from 0.5 to one. For the animation. I'm going to use that spring animation. Define response of zero-point 85 and damping fraction of 0.6, I believe, blends duration as default value. And let's hit Play to see how this looks like. Okay, just, there is maybe a slight bigger gap then I would like to have between text and our latae file. What I can do is to decrease the height to 200. Finally, we will add the black overlay to the rest of the screen. What we can do is defined frame of max width of that infinity, max height of that infinity. And after this, define another big round view. So by default, this is the blue color. We will specify color that black dot opacity of 0.5. And in order to ignore the safe area, I can type ignores safe area. All great. Let's just see the final result. So you'll see nice little spring animation for our background pop-up. Now, what's left to do is to show this loading pop-up inside our register profile view. So I can go to register model. Here. I want to define new published var called loading. By default, this is equal to false. And if our fields are valid, then I will change the loading to true. Inside the register profile view, I will embed our scrollView inside the z stack. So this is the end of z stack. And here I will specify if register view model is loading. Then show the loading view. In order to see how this works in simulator. Let's first common this so that we don't navigate immediately to our home view. If we tap on register, we see our loading view. 46. Firebase Setup: In order to use Firebase, your iOS app, the first thing you need to do is to sign in with your Google account. And after that, you need to click on go to console to go to your main dashboard. Here we have overview of all our Firebase project. Project is our container for your app. And it contains all the feature that Firebase can offer to your app. We're going to create a new project. So let's start with creating a new project. I'm going to call this Stacy demo. Hit Continue enabled. We will only do this for this project. I'm going to disable this. So I don't want AB testing and all these things that Google Analytics offers to me. But if you want to have some of these features, then you might been able this Google Analytics, Okay, Create Project. After this is done, are now new project is ready. And we will go to this word. So on the left side of our project, there's word. You see all the available functions, all the available features and those Firebase can offer to you. For now, we are just will be using authentication and cloud Firestore. So I want to authenticate my user through the Firebase. So I don't need to build my custom authentication service, but Firebase can provide that to me. We will start by adding Firebase to our iOS app. So I will tap on iOS. Here. The important thing is to enter the Bundle ID. This is the Bundle ID of my project. I'm just going to This everything in lowercase and copy and paste this to Firebase. App nickname, let's call it stays see them all. And UPS Store ID is optional. I'm going to skip that for now. Okay. The next the most important thing is to download the school service in for Bill is filed and molded to our application. So let's dial all this. And in the Xcode, I'm going cool, drug and drop these serifs, be released and add to all available targets for now, I just have a target for Stacy demo. That's fine. Okay, The next thing is to add the Firebase SDK. Here, it recommends that we use CocoaPods to install the Firebase SDK. I'm going to skip that and go to next. Okay, initializer code. Next, click to continue to console and finish. The adding of Firebase is the key to our app. By using Swift package manager. I will open the Firebase iOS SDK on GitHub. And here I have Swift package manager for Firebase. This currently in Beta. But I have tried and it works pretty stable. So we all go through the installation steps. In Xcode. I need to install Firebase. We are Swift package manager, so we need to link our project to this Swift package manager. Okay, I'm now in Xcode file. So your packages at Becker's dependency, I'm going to paste this Firebase iOS SDK. Click Next. Leave this as default next. And finally, we can choose the baggage products from our Firebase. I'm going to select Firebase out. Also Firebase Firestore, and finally, Firebase, Firestore, Swift. You are free to choose any other package from Firebase. For now. I'm just going to add these three. Kids finish. Okay, we can try to build our app. And once we add Firebase, you might see that the build time increases. Once you build the app for the first time. Great, the build tasks he did, and now we are ready to use Firebase in our application. One final thing we need to do is to initialize the Firebase inside our, they are Stacy demo app. So I will go to Application Stacy demo app. And here I need to import Firebase first. So import Firebase. And here I declare int and call Firebase app. That configure. Just in case I'm going to run this on simulator to make sure everything is fine. 47. Register New User in the Firebase: Let's start using Firebase in our application, in our user registration flow. Here, I am in out service and I want to implement a register function. The first thing I need to do is to import Firebase out. And also I need to implement Firebase Firestore. In order to communicate with Firebase Firestore, I will need to create on your private DB var, and that will represent the Firestore. Firestore. This is the database on Firebase. So we will start by removing these to-do. And here I will call out out to access Firebase, authentication, gloss. And now I can call create user function email. These columns from user dot email, password comes from user that password. And finally, we have the completion here. The completion takes two arguments. First one is out result, and second one is optional, and this is the error. The first thing we need to do is to create our new guard clause and check whether or not the error is nil. If the error is not nil, then what we will do is to call the completion with this error and simply return from further execution. Okay? And now, once we are sure that there is no error, we can check what is the result. The South result is optional. So I need to on rapid. So if we, if we cannot get the value, we are going to simply return from here. Otherwise, what we want to do, so if we have created a user with email and password, then we want to store all user information to our Firebase, Firestore. We are going to create a new collection in Firebase. Firestore is our NoSQL database, so all data is stored as a collection. What we want to do, we still call the database and then access the collection. Here, the collection name is going to be users. But we want to store this not as hard-coded string, but instead, I'm going to create a new file to store all our constant strings. So I'm going to create a new file called constants. This can simply be struct called constants. And here I will defined Firebase collection that we are going to use. So Firebase collections, the first one collection we are going to use is named users collection. This is the, the value of our constant and the actual string value is users. The second one collection that we are going to use a little bit later is for storing all our room data. So I'm going to call this room's collection. Okay? And now if we go back to out service here for collection fat, I can say take constants, user's collection and that new document from user. So this is going to take user and add new document to our user collection. In order to remove the error we have. At the moment, we need to go to user class and may disclose quotable and identifiable. So we need to make it identifiable and quotable codon meals. And that we can convert this user class to JSON and from JSON to type user and identify all means that we will have an ID property and this ID property uniquely identified as our user. Here, I will also import Firebase, Firestore, swift. And for our ID, I will prefix it with document ID. You are using this document ID property wrapper in order to store our user to Firebase with ID of strings. While we're here, let's also extend our user class a little bit with our on-boarding details. As you remember, we had some data that we were storing in user onboarding details, struct, and now we want to bus that data as well to our user. So we have room type. By default, this is empty string. Next, we have the moving location. This will be also empty string by default. Then we have move-in, date. Make it as date, as default value. And the last one we have MUX, rent. This is the type of double, and by default this is 0. So I'm going to create another function in our user name set on boarding details tool set, this onboarding details. And for role-type, I'm going to take on boarding details, that room type for location. I'm going to take on boarding the dot location for moving date. I'm going to take our morning details that Moving date. And lastly for max rent, I am going to set these two or morning details, that mock Surette. Okay? The final thing, what we need to do is to specify which keys, which properties we want to store in our Firestore in Firebase database. I want to store everything but password and confirm password. Since we are using Firebase for authentication, we don't want to store password and confirm password as plain shrinks. Instead of that, we are going to omit them from storing them in the database. In order to do that, I need to define private enum coding keys. So here I need to specify all the keys I want to, all the properties I want to store in the Firebase. So I will have case for everything but password and confirm password. Okay, I have our coding, I have my coding keys. And here also specified our new field called User ID. This is the string. So what's happens inside Firebase Authentication is that we are authenticating, that these we are creating our new user email and password, and we are getting the user ID. And then I want to take that user ID I get from registering a new user. And populate the user ID with that newly created user ID. Here, I also have an error. So since I'm not specifying password and confirm password, I need to change them to var and have the default value. Okay, Does the first error, but the rest of this looks fine. And the second error that we are calling add document, but this can drop. So we need to wrap that with try and catch. I need to specify do and call this width try. And also I need to have catch. In case we have some kind of register error. I want to call the completion block. With that register error. The final piece in our register function is still called User dot, user ID. And take all result user. And you ID. User ID is lead constant, so I need to change that to var. And now the bid should be fine. This completes our register function in our service. Now we can go to a register, your model and start using this out service. The first thing I can do is to define private let Alt, service. So this is the service we have for authentication. And then here instead of register user, I will call out service and register. The user is the one we are creating above. And we also have completion block here. The first thing we need to do is to check whether or not we have some kind of error. So the error is equal to nil, then everything is fine. But in case we have some kind of error, then what we want to do is to set loading. The false registration Successful is equal to false. We're missing reference to self and we will simply return from further execution. Since we are changing published properties that are affecting the UI, we made to make sure that we are on main thread. So we are making sure that by setting these pit q dot main. And I will also include some kind of delay for user to see our loading. Your. So async after deadline is now plus two seconds. And here we want to execute setting, changing, loading and Registration Successful to false. We also want to set error occurred equal to true. And register error. In our case is error dot localized description. This is the case where were we have an error during the user registration, but in case we don't have ever, what we can do is to set our loading to false and set registration Successful equal to draw. One final piece that we need to pass to our user is all these user onboarding details. If you remember, we have used our environment object user onboarding details to store all details about registration. And now what do I want to do is to take those onboarding details and pass them through during registration. So I will pass them through the register function. So I need to go to register your model. And here, extend this register to take on boarding details. And if user is valid, then I can set onboarding details. Okay, let's go back to orange, Sir profile view. And here, call this register with our morning details. Let's build this. And now we should have everything in place in order to register our user. Before we test our iOS application and our registration flow, what we do, what we need to do is to go to the Firebase and set up the authentication. So we need to get started with our, our dedication. And said, What kind of signing do we want to provide? You have different options, so you have email password, you can login with Google, Facebook, Twitter, GitHub, Microsoft, or Apple. I'm going to enable email and password. Okay, Great. And now for our Cloud Firestore database, I need to create a new database. So create database. And I will start in test mode since I am testing the application. But you can, but you should always make sure that you start or change later to production mode in order to have a better security of your database. Okay, Next, our location is going to be Europe, since this is the closest to me. And click Enable. Before we test our registration, let's just make sure that after we add a new user to the Firebase user's collection that we call completion with nil. Okay, let's stop on get started. We'll soil select room. Let's say Paris, change the max rent to 1 $1000 per month. Moving date can stay as this top or next. I will populate all these fields. And once we tap on register, we get the loading pop up. And after our registration is done, we are navigated to hello, home, to our home view. If we go to Firebase and to the authentication section, you'll see that we have our new user that we have created. Here is the user ID from the dedication that we got. And we are passing this user to Cloud Firestore, to our users collection and to our user ID. All other fields are also correctly stored. 48. Login Functionality: Once we register a new user, then we can implement our login user function. So instead of this to do, I'm going to call that out and simply call sign-in with email and password. Email. We are passing that to the login user. Password. Same thing. Here. We have the same completion as in our register function. So we can copy and paste this part of code. And also called the completion on the bottom of our sign-in closure. And that should be it. So as you can see, if you are using Firebase authentication, you can really quickly perform create user and also signing. In the next lecture, I'm going to show you how to implement password reset. And you also see that it's also pretty straightforward as it sign in. Okay, let's go to login ViewModel. Here we have our OUT service. So we have called our login user and past e-mail and password. The last thing we need to do is to check if we have any kind of error. So if error is equal to nil, then we can say that we have successful login. Otherwise, we would like to display on alert what went wrong. So we will have similar implementation as in register ViewModel. So I will have error occurred and login error published fields. So instead of register error, I'm going to say login error. And here in the else block, I will say error occurred is equal to true. And our login error is equal to error. I'm going to force unwrap this since I am checking whether or not the error is nil. So if we get to this else, I know that this error exists for sure. Okay, let us go to the login view. And here we can specify the alert. So the alert is presented in case we have our error occurred, set to true. And for our content of our alert, I need to create a new alert. The title is Text error. And the message. We will get that from the localized description of our error. So I can specify the text that will take login model dot login error. Here I have $1 sign extra. And now this should build. And we should be able to perform login to our application. If we tap on Login button without entering E-mail address, then we get the error validation from Firebase that the password is invalid or the user doesn't have a password. But if we enter the valid credentials and top on Login, then we also navigate to the Home view. 49. Password Reset Functionality: In this lecture, I'm going to show you how to use Firebase authentication in order to set on email with password reset instructions to the user if the user has forgotten his password. So we are again IN OUT service. And here, instead of these two, do I need to implement password reset functionality like creating a new user and performing sign-in. Password resets is also really simple to implement. In Firebase. We just call OT OT and sent password reset with e-mail. So we will provide the email. And in our completion handler, we get the error. For now, I'm just going to ignore this error and call this completion. If we go to the password, resets your model, we don't have to take any further action in password resets ViewModel, since we have already connected our ODE service with our password reset view model. In case you are wondering what kind of email is going to be sent to our users. So you can go to the authentication. And here inside the templates, you have option for password reset templates. And you are free to choose to edit this template. So I can, let's say, change the subject. So I will say reset your password for Stacy. Demo. Also here I will just expand here to say hello from Stacy Dell. And I'm going to save this. Okay? I'm here in my application and I tap on forgot password. And let's say that ninja Josh has forgotten his password. That's okay. An introduction. You don't have to apologize. We will quickly perform password reset. So I will enter the email address and up on send request. And now the e-mail with password reset instructions should arrive to this email. Yes. This is the real email. I have registered this domain. Okay. I'm in my inbox and you can see I have got the recipe or password for Stacy them or e-mail. And here I have instruction on how to reset my password. So I need to follow this link. And here I can specify a new password if I want. 50. Implement Persistent Login: At the moment, when we are starting our app, we are always displaying our on-boarding view as the first view that is presented to the user. But we don't want that. We want in case the user has seen the onboarding view. We don't want to show it again. Also, if the user has registered and logged in, we want to show the home view. Otherwise, if the user hasn't logged in, then we want to show the login view. So in the, in this lecture, we are going to implement this kind of persistent login. And now I'm going to show you how to do that. The first thing we need to do is to specify some constants for our flags that we are, we are going to use to control which view is going to be presented first when we launch the app. So here I need to specify some flags. The first one is static, let logged in. And this flag, we'll represent whether or not the user has been logged. In. The second flag we need is to indicate whether or not the user has seen the onboarding screen. That is, if the user has seen the onboarding one time, we don't want to show it multiple times. So I can onboarded. And the last thing we need is a flag for current user. In our, with our current user, we are going to use this constant to store our current user in. User defaults. Great, with help of these flags. Now, I can control our flow in Stacy demo app. So if user defaults that standard bowl for key, let's say constants, dots, log n. This means if user is logged in in our app, then we want to show home view as the initial view in our flow. Elseif. If the user has seen the onboarding view, then we don't want to show the onboarding view twice. So we need to make sure that user default, that standard bool for key constant. Or more that if that's equal to true, then we want to show login view. And finally, if we are starting the app for the first time, then we will present the onboarding view. Okay? Now we need to set the onboarded to true in our onboarding view. So here in appear, I'm going to set user defaults, dot standards. Set true for constants not on-boarded. And now the user should see the Onboarding. We'll all the ones. But when we open the application for the second time, then we should be presented with our Login view. Great, here is the first time. So we can start type on get login. But if we run our application for the second time, then we are presented with our Login view. The final step that we're missing is storing our current user in UserDefaults once the user has been locked in. So I will create a new function, new private function called save user to default. And here I want to pass the user ID so that I can get all user data based on our user ID. And then I will store all that in the user defaults. I'm starting with db dot collection. I want to get the user's collection. But I want to filter where field named user ID is equal to user ID. To get all these documents, I will top get documents with completion block. So query snapshot will return all results. I'm going to say here is SQL query snapshot. And we might also have some kind of error while fetching all these data. So if error is equal to error, then we want to return. We don't want to perform our Savior's or two defaults. Otherwise, let's make sure that we have some documents in our query snapshot. So I will guard let documents is equal to query snapshot documents. Else. I also don't want to proceed since we didn't get the documents. And finally, I will get my user by trying to get from documents the first element and get all data as user type. So in case we have this user, then we can go to UserDefaults, that standard and set to true our Bool value for constants dot logged in user. And also we can encode this user and save that to user defaults as well. If let encoded is equal to, let's try two. Use JSON encoder to encode this user. So if we succeed with that, then we will also call UserDefaults that standard and set encoded value for key constants that current user. So we the JSON quarter, we are converting our user to JSON format and we are saving that to user defaults. I can silence nice warning by changing these two error different from Neil. And in my login user. Here, I should call save user to defaults. And in order to pass user ID, I will call out result dot user that UID. In order to return current user from UserDefaults, we can use these current user method. So the first thing I'm going to check is whether or not we have current user in OT, dot, dot, dot, current user. So we need to make sure that this is different from Neil. Then if this is equal to nil, then we just return nil. This means that we don't have current user and that we don't have anything to retrieve from our user defaults. Otherwise, let's use our user defaults to get this saved. User user defaults. Standard. We will retrieve object for our key constants, that current user. This will return data. And we can use the colder. That is the JSON decoder, that is the JSON decoder to try to load this user. So if let loaded, let's call it the person. And we will try to use our decoder to decode, to type user itself. We want to decode saved user. Since we get, we got that as data. If that succeed, then we can return loaded person. Otherwise, I will return nil here. Let's see this in action. I will login with our user. Great, we are sealing this hello home. So we are in the home view. And now if we try to run the app, again, we are taken immediately to our home view. 51. Implement the UserCellRow: We will kick off this section by implementing the top part of our room cards. So we will implement this user sell rope. It consists of our at our image, user name and type of the user. And in the next lecture, we will implement the rest of the room card. Let's start by going to the subviews. Right-click on the subviews and new file. I'm going to create a new swift file and name this user cell. Bro. Okay, since this is going to be reusable, user seller 0, what we want to do is to define three arguments. So we will have user, this is going to be username. And this is the type of string. Next, we have user type. This is also the string. And finally, user avatar. This is going to be image of our user, our router. Since we are calling user seller oh, from our provider, then we need to fix the error we have in the provider by providing some defaults values. So user, I can type Susie Jenkins, user type, roommate, and user outer. Susie. This is the image in our assets in our roommates. So this is the Susie. Let's just resume, resume the previous so we see what we have so far. So we should only have Hello World text rate. Let's start by defining the age thick as our main container. And here I will define image with our user, our avatar. I'm going to make this image as resizable. I will scale it to feel. Define custom frame of wheat, 40, height 40, and remove the alignment. Finally, let's put the clip shape. So if we want to have rounded image, then what we can do is to define the clip shape for our image so that we have our image inside the circle. The next thing I need to have these stack. Then inside the VCE deck, I'm going to put username and user type. The alignment is leaving. And we will put spacing of two. Here we will have two texts. First text is for user. So this is the user name. Font-weight, semi bold, and foreground color, this title. So title is our custom color. We have defined in our assets and in our extensions, we have Title. Grid. Remaining thing to do is to add user typed text. Foreground color of text, and font will have a smaller formed. So I will put a caption for our stack. Let's just add some leading padding of eight. And after the we stack, we can add spacer in order to move everything to the left. So I will just want to have a little bit horizontal padding. And hi little bit of padding at the top. 52. Implement RoomRow: Let's continue with implementation. And now I'm going to create a new file. New file, and call this room role. Their role is the complete cards that the user will see for one room item. And in order to have display all data, we need to define our new model. I will call this model room. This room model will contain all data that we need in order to present this room row. So right-click on models, new file. This can be swift file. And I will call this room. So this is the struct room. It has to be identifiable and also countable since we want to uniquely identify each room. And also we want to be able to download and upload rom data from Firebase. We will also import firebase, Firestore swift, and define the document ID for our room. This is the optional think. Let's define couple of properties for our room. So we need local ID to uniquely represent our own inside our app. We also need the information about how many beds does the room contained. Next, we need to have some kind of short description. This is string. Next, price per month. This can be int. Next. One of the most important thing is still defined the image. This is string as well. The next thing is the user that offers this room. Also user type, and also user outer. And we controlling the final thing to indicate whether or not the room has been booked. I will also define some dummy data. This data we will use in order to design and implement our Swift UI views. In the resources section of this lecture, you can find this completed a room and you can find this dummy data. Great. So let's get over to our room, or 0. And now we can define room that we will use to implement design of our room URL. Here we are missing the perimeter for a room. So what I can do is to use our ROM data and take the first element from our own data in order to implement the design. Okay, let's resume the preview and the resume again. And now I can start implementing this room URL. I will start with, we stick and define the alignment of leading. And inside our room role. The top part of our URL row belongs to User cell that we have implemented in the last lecture. I need to pass the arguments for our users seller oh, and I can get to all of this from world. So we're wrong. Dot user, user type, room, that user type and user out our room. That user outer room image is next. So I create image and specify room that image. I will make this resizable. And also add frame of height 240. Below the image. We have the information on how many beds are available in, in this room. So I can add text for specifying how many bits do we have. And I get this information also from room that that's formed is caption. Foreground color is dot bed. Again, this is the custom color I have previously defined. And I will add some padding to the top of four. Also add spacer to make sure the text is aligned to the left and add some horizontal padding. Below this calms the text with short description of our room. So we can get this from room. That short description. This is the bold text. Foreground color is titled. Font, dot title three, a little smaller. Then title. We can add horizontal padding. And we can also add vertical bedding of, let's say for rate. One final piece of information we need is the actual price per month. So text. And we will have per month the price. Let's just put room that price inside of this text and put the dollar signs before our rule price. Okay, We can quickly style this. So font is sub-headline. So this is a bit smaller. Size. Foreground color is dot text. And I will also add horizontal padding and a little bit of padding at the bottom. The final thing, I can also add additional padding, bottom of eight to our complete room row. Now we have our reusable wrong card that we can display inside the list. 53. Display Room Data in List: In this lecture, we will present all the rooms we have in our ROM data inside the room list. So I'm going to create our new modules and call this room listing. And here I'll create a new file, new Swift UI view, and call it ROM listing view. Also, I'll create a new file, none of your model fraud for our room, listing view. And Romulus think ViewModel will be in charge of getting the data for our own room holistic view. So next, and here we have room listing your model. This is the class room, least think ViewModel. And this is the observable object. We will put published var of rooms. So this is the array of our own data. And we will initialize this with our room. Dummy data. Great. We have our ViewModel. Now we need to implement our view. The first thing, what we can do is to define our new state object for our ViewModel. This is the state object var room listing your model. And I can implement this immediately. So our own listing, viewModel contains our data. In order to display the data inside the view. There are different options. The first one is to use list, and you are free to use list and display data in a single table. However, I'm going to do a slightly different option. So I'm going to use the combination of ScrollView, which will have vertical scrolling. Inside this scroll view. I'm going to use lazy. We stack. So if you'll remember, we use lazy. We stick to display views inside this stack in such way that only views that are visible inside the visible area of the screen will be rendered. And in case lazy, we stack has additional items which are not visible. They won't be rendered immediately, but only after the user scrolls down to those views, they will be rendered. So this is a great option for lazy loading. And finally, we can iterate through our data by using for each. So in our wrongly think ViewModel, we have our rooms and the id is the local room. Id. For each will get us the wrong item. And here we can call a room role and pass the item as our room. Okay, if we hit Preview and heat alive, we get this data in list. Again. I am using this approach where I have ScrollView Louis XVI stack and for each instead of list. Since I think this approach is more customizable than using the least alone. What we can do is to add some background to our room row. So we will have background. Let's define color, primary, color, color, invert dot, add shadow. Color for our shadow is black color, so color black. But we will add the opacity of 0.6. Radius is four x 0, y of 4. So with this, we have added a little bit of styling to every room row. And finally, I will also add a background to our lazy, we stack. This is color dot table background. Now if we preview this inboard in both light mode and also in dark mode, we should have support for both. 54. Fetch Room Data From Firebase: In this lecture, we are going to upload the wrong data to Firebase our data that we are currently using locally. And after that, we will download and display data in the list. So I can start by embedding this scroll view in negation rule and defined the navigation title of rooms. Great. I will remove this preferred call color scheme and use the default. And now what I can do is to go to home. In here called Room listing. The reason we are separating our home view from our room listing view. Since the home view is usually overloaded with other things. And by separating wrongly think View from home view, we are just splitting things into smaller, manageable views. Now, if we try to login to our application and we navigate to our home view, we should see the list of rooms. If we test our app alittle bit and want to create a new user and go through the registration flow and want to register a new user. You will notice that once we register a new user and go to the Home view that we have to navigation views. The first negation of evil comes from register profile you. And this is something that we want to eliminate. The second navigation view comes from listing view. This navigation view is fine, but what we need to do is to hide this navigation view. What I can do is to go to Home you. And below our z stack specify navigation bar hidden and set that to true. This should eliminate the first navigation bar and just leave us with navigation view from room, please. Thank you. Okay. The next thing, what I would like to do is to upload data to Firebase. And after that, I will like to download that through our room listing view model. We will also create a new service for downloading data. But the first thing I would like to do is to import. Firebase, Firestore air here. In the initializer. I can specify DB. Firestore. Firestore. Loop through our aerobes in the room data that we have and use our database and store a collection called constants. Rooms collection. We would like to add document from our room. Sees this can fail. I will add optional try. Okay, we are in the home view. Nothing has changed here. However, if we go to our Cloud Firestore and inspect our collection, you'll collections, you'll notice that we have a new collection called rooms, and here we have all our data. Great. I can now comment out this, so I don't duplicate data in Firebase and start downloading data from Firebase. I will define our new service. So new file, new swift file, and call this room service. I need to import Firebase and also import Firebase far store Swift. Let's define this room service and define new dB, which is far store, not Firestore. I will have one function called get rooms and define our completion block. This is the escaping completion data that we will get our rooms. But this is optional. And this returns void. Similar to what we had in our out service where we fetched our user's collection. We can also use the same approach to download our room data. The only difference is that we won't have any filter on field. So I can copy and paste this code. And I can download rooms collection where field is not needed. If error is different from Neil, we'll call completion nil and return. Well, the rise, we need to get our documents for our from our query snapshot. If we fail to get those documents, we will also call completion of Neil and return from further execution. Otherwise, what we can do is to define fetched rooms array. And this is the array of room and iterate through our documents. So for document in documents, and try to convert this to URL type. So if let ROM is equal to, let's try to get a document data as room type. So as ROM self, if we succeed with that, we will add to fetch rooms this newly created role. And once we iterate through all documents, we will call the completion with fetched rooms. Great. I have my room service that will download the rooms from Firestore. Now, I can go to Rome listing your model. And in the initializer, I can call this room service. We need to define private var room service. This is our new instance of room service. And in the initializer, I will call a room service dot get rooms. With completion. That gets me fit rooms. Since this is optional fetched rooms. First, I need to check whether or not we have any kind of rooms. So if let fetched rooms is equal to fetched rooms, only, then we can set our rooms thought fetched rooms. And by default, this is going to be empty. We need to capture self here in order to be able to access the rooms. Warn other thing we need to do is to rob this inside this pitch q dot main to make sure we are making changes to our public property on main thread, dispatch queue and that main async. And let's put this code inside this page, Q dot Min. Now, if we run our app, we get the same data. But now the data comes from cloud Firestore.