SwiftUI: Learn How to Create a Colorful To-Do List iOS App with Core Data and Xcode | Robert Petras | Skillshare

Playback Speed


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

SwiftUI: Learn How to Create a Colorful To-Do List iOS App with Core Data and Xcode

teacher avatar Robert Petras, UI Design & App Development with SwiftUI

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

11 Lessons (2h 41m)
    • 1. Project Preview - What we are going to develop with SwiftUI and Core Data

      0:57
    • 2. Let's set up the Core Data project with SwiftUI and fix Xcode's template

      12:59
    • 3. Introduction to Core Data and understand the Xcode's Core Data template

      26:34
    • 4. Let's create a basic to-do app from Xcode's Core Data template

      16:04
    • 5. Let's develop a stellar app design

      7:18
    • 6. Create a new entry form for the task item

      17:08
    • 7. Let's develop a custom header

      12:55
    • 8. Improve the individual task item view

      14:52
    • 9. Learn how to create a custom visual effect in SwiftUI

      10:00
    • 10. Dealing with UX and Sound Design

      10:36
    • 11. Introduction to the new Widget API

      32:04
  • --
  • 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.

32

Students

1

Project

About This Class

b5923697.jpg

What is the main project of this class?

In this SwiftUI tutorial, we will develop a task manager iOS application with Core Data integration. This is not a project with a boring user interface. This iOS and iPadOS application provide a professional UI/UX design.

f6fe390e.jpg

Who is this class for?

This SwiftUI class is suitable for anyone with some prior iOS development knowledge.

81f6d48b.jpg

What is the difficulty level of this class?

The difficulty level of this SwiftUI class: INTERMEDIATE LEVEL.

d592e9e1.jpg

How can students get feedback from the teacher and other students?

  • Students can share screenshots of their finished projects with the teacher and other students on the Skillshare learning platform by creating a new project in the class.
  • By doing that the teacher of the class with many years of experience in the app development industry and other students are able to give feedback to the students.
  • Students are encouraged to use the comments system and share their learning experiences with us as well.

d074211f.jpg

Technical requirements

There are only two technical requirements for this SwiftUI class:

  1. macOS Big Sur operating system from Apple (free)
    https://www.apple.com/macos/big-sur/

  2. Xcode from Apple (free)
    https://developer.apple.com/xcode/

1e263a92.jpg

Start your SwiftUI development and UI/UX design journey with this hands-on project and learn by doing. Without further ado, see you at the class!

Learn how to integrate Core Data with SwiftUI

Apple's Core Data framework helps developers to manage and interact with data on a persistent store. It works on iPhone, iPad, Mac computer, or even Apple Watch.

When we start from a brand new project, the easiest way to use the Core Data framework is by enabling the Core Data option on the setup screen. By doing that Xcode will generate all the required file templates with code and the managed object model for us.

This Xcode 12's new Core Data template comes with the SwiftUI app life cycle integration and the required Core Data Model. This is why it is worth knowing how to get started with this new template and how to create a working application.

e2885d82.jpg

Topics will be covered:

  1. How to integrate Core Data with the SwiftUI App Life Cycle
  2. How to get familiar with Xcode's new Core Data template
  3. How to create a basic Widget for iOS and iPadOS devices
  4. How to develop a Widget sets with different sizes (small, medium, large)
  5. How to set up the Preview to test the different Widget sizes on the Canvas
  6. How to Create, Read, Update and Delete a database item (CRUD method)
  7. How to show SwiftUI views conditionally
  8. How to switch from Light mode to Dark mode the app's appearance
  9. How to store the app's appearance using App Storage
  10. How to create a visual effect with SwiftUI (blur, overlay, display mode)
  11. How to add the required assets for the Widget extension
  12. How to develop a custom Toggle style and make a checkbox
  13. How to improve the User Experience with sound effects
  14. Practice how to use Apple's Feedback Generator and implement haptics

App icon design

b7928f43.jpg

App launch screen design

44bb059a.jpg

App widget design

d6005247.jpg

Meet Your Teacher

Teacher Profile Image

Robert Petras

UI Design & App Development with SwiftUI

Teacher

Hello, I'm Robert Petras. I teach UI/UX design and iOS app development with the Swift programming language in Xcode. 

In my opinion the best way to learn native mobile and desktop development is to learn the Swift programming language and master Apple's latest user interface framework: SwiftUI 3. You can create applications with less code using SwiftUI in the Xcode editor.

I'm pretty confident that you will enjoy the development process and you will be satisfied by looking at the finished applications while creating the main project in each class that I teach.

Recently started to teach iOS, macOS, watchOS, and even iPadOS mobile app development with SwiftUI which is a native User Interface framework invented by Apple.

Appl... See full profile

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
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.

Transcripts

1. Project Preview - What we are going to develop with SwiftUI and Core Data: In this swift UI tutorial, we're going to develop a daily personal task management application. It's not a typical IS project with a boring UI design because it delivers a personal touch and feels. So what topics will we cover? First, we will learn how to integrate core data with the Swift UI app lifecycle using Xcode's new template. Second, we will get familiar with how to create widgets for iPhone and iPad devices. Finally, we will practice how to design an emotional app user interface for adult to-do list. You know, people can't stand boredom for a long time, which is why apps that are built for non exciting, repetitive tasks so often get abandoned on phones. But not this project. If this is something you want to learn, then launch Xcode editor and start coding along with me. 2. Let's set up the Core Data project with SwiftUI and fix Xcode's template: In this swift UI class, our primary goal is to get familiar with the core data framework and develop a fantastic Task Manager from a boring to-do list application. While we are having some fun. By doing that, we will also learn how to store, retrieve, and update some content using Apple's native persistent storage. Each lesson will be straightforward and we will develop either a new feature or covering an interesting golden nugget about the powerful Core Data Framework. So you and me, together, we will build up this impressive application step-by-step and land by doing, if this is something you want to learn, then launch Xcode and start coding along with me. Setup. All right, let's get started. Open the resources folder downloaded from this section. As usual, there are three additional folders and a supplementary workbook document. Inside it. You will find the source code of the finished project in the green folder. It can help you when you get stuck and need some quick assistance. In the pink folder, you will find all the resource materials. Finally, we are going to save our new project in the blue folder. Great. Now let's open the workbook document and take a brief look at the learning objectives. As you can notice, there is a comprehensive list of the topics we're going to cover in this tutorial new project, awesome. The second step is to launch the latest Xcode editor. Then create a new Xcode project. Make sure that their iOS or project is selected at the top menu bar on the new window. Then choose the app option from the available templates. Finally, click on the Next button to create the project configuration. Now, we need to configure this new core data project for the product name, enter devote for the team. If you already have an Apple developer account, logging in here allows you to build your app on a real device. If you don't have an Apple developer account, you can skip this part and test your app in the iOS simulator on your Mac organization identifier, we usually enter our website address in reverse order. For example, com dot swift UI masterclass. Please make sure that your organization is different so you can compile the provided finished project if it's necessary. The bundle identifier is automatically combined from the project name and the organization identifier. Next, the interface must be swift UI. Then the lifecycle must be swift UI app. After that, make sure that Swift is the selected language. And here goes the most important setting for this project. We must check the Core Data option without the CloudKit integration. Then leave the include tests options unchecked as well. After all of the necessary settings. Click on the Next button, and now we need to tell Xcode where we want to save the core data project on the computer. Please navigate to the students folder as the destination. As I do. Now, click on the Create button and Xcode creates all files and folders for this fun project. Resources. Splendid. As we did many times before, we'll start the development by adding the pre-made resource materials to the project. First, select the assets catalog in the project navigator panel. Then click on the app icon in the middle panel, we can see an empty set of icons on the right part of the editor. Now right-click or control-click on the app icon group as I show you, by doing this and you can textual many will show up, select the Show in Finder option from this many. And Xcode will bring us to the projects icons folder in a new finder window. Next, open the app icon set folder. There is only a content JSON file in it. Now in a new tab window, navigate to the icon folder. In the resources folder, you will find the pre-made app icon in many different sizes. First, select and copy them to the clipboard. Next, we're going to add this set of icons to the project. Jump back to the projects that icon folder and paste everything from the clipboard into this place, you will be asked to replace the existing file. Obviously, click on the replace button and we are good to go. Excellent job so far. Asset files. Now it's time to add the rest of the asset files to the project. Go back to the Resources folder, then select the color and image folders there. After that, drag and drop these folders into the middle pane of the editor as I show you. Great. As he notice, we got a background color, a logo, and an image file. Now, we're going to add sound effects directly to the project instead of the assets catalog. First opened the sound folder, then drag and drop all mp3 sound files into the devote folder in the project navigator pane as I do when a new window pops up, select the copy items if needed. Under the Create Folder references, options. Before you click on the Finish button, make sure that the project is also selected as a target. With all this prep work, we are ready to develop the core data application folders. But before we start coding, we will create all folders that we need beforehand. I highly recommend you trying to prepay your folders and kites structures in advance rather than later on. That said, select all MP3 files and group them into a nice sound folder. As I show you. Now select the content via swift file and create a new group for the selection. Name it to view Sepah. After that, Let's create the following empty groups. Extension. Then another one, utility. Now let's create another one called style. Finally, select the two new files that this core data template provides us. The fast file is the persistence file, and the second file is the devote data model file. Now from this selection, Let's create a new category folder called model. After that, we can reorganize these folders by dragging them in order as we like. So far, so good settings. Next, we're going to make some changes in the settings. Select the main project on the sidebar, then select also the devote target in the middle pane. After that, make sure that the landscape left and right options are unselected. This application works better in portrait mode. Now it's time to set up a new launch screen. First, click on the Info tab item at the top menu bar. It will show us the predefined app settings. As you may already know, this property list consists of key value pairs. That is what we will modify here. Right now, there is an empty launch screen dictionary. Click on the plus button, then select the background color key. As I show you. After that, enter the following value. Backgrounds dashed color. Perfect. Now let's add a new image to the launch screen as well. For its value, enter logo. Nice. The last thing that we need to do is to add here following parameter from the drop-down list. Select Image respects safe area, insets option, then change its Boolean value from 90. Yes. Guess what? Our new launch screen is done. The problem, alright, first, select the content view file and take a brief look at the preview. Do you see the list with some sample data? This is what Xcode's default core data template gives us when we choose to use it as a starter code for our project. Now, you may think this code is correct, but in reality, there is something that makes it useless until we fix it. And that's precisely what I'm showing you in the rest of this lecture. The very best way to prove this template is broken to test the default core data template by building and running the project either in the simulator or on a real device. So let's do it right now. When we build and run the project, first, we should see a pink background and the white logo on launch screen. But shortly after the screen transition from that to a completely blank screen. As you can see, there is no list with the sample content. Moreover, there is no navigation bar with some buttons. So what's going on? It turned out that Xcode's shipping a broken core data template, but do not worry because we can quickly fix it. The solution. First, switch back to Xcode and navigate to the end of the list view. They enter a new comment for this view list. So the problem with this layout is that it's trying to use the new toolbar API, but to do it in the right way is to add a navigation bar first. That's why we get only a blank screen in the simulator. To fix it. First, we need to embed the ListView into a new Navigation View. Command Plus click on the list name, then select the embed option from the contextual menu. As I show you, it will wrap the list into a new place holder container. Now we need to enter Navigation View. And as you can see in the preview window, a new edit button was added to the screen. We are not finished yet. Add button is still missing there. But why is that? You know, we need to make our code conform to the new toolbar API. And one way to do that is to put each button in this toolbar into a dedicated toolbar item. So let's do it. First, add a new comment at the end of the toolbar. As I do, enter a new comment, end of the toolbar, then add another comment after it. New comment, end of the navigation. Now here comes the real deal. Embed the Edit button into a new toolbar item. As I show you, enter toolbar item, navigation bar, leading. After that, we need to fix the Add button. Similarly, enter toolbar, item, placement, navigation bar, trailing, and you know what? Both the Edit button and the Add button are placed on the toolbar as they should be in the very first place, in my opinion. But as always, the proof of the pudding is in the eating. So let's see how our code works in the simulator. Let's build and run the project C. That's much better now, we can add a new sample data by tapping on the toolbars plus button. Let's try it out a couple of times. But not only that, we can delete the list items by switching to the edit mode as well. Look, this core data starter project works now and the fixed wasn't that hard either. I really hope you enjoyed this introductory lecture and you are ready to get all the necessary information about the core data framework in the next class, I can promise you that by the end of the next lecture, you will have a fully functional Todo application on your hand. That's being said, See you at the class. 3. Introduction to Core Data and understand the Xcode's Core Data template: In this lesson, we're going to learn about apples native persistent storage, and the core data framework with Swift UI, we will mainly focus on three topics. First, we will learn what core data is and isn't. Second, we will take a look at the Core Data stack. And last but not least, we will get familiar with Xcode's generated core data project template. So without further ado, let's get started. First of all, what is chordata? Chordata is a native solution provided by Apple to store, retrieve, edit, update, or delete data permanently on a local disk. It's worth knowing that core data is also available not only on iOS and iPadOS, but on macOS, watchOS, and even tvOS as well. What is chordata? Chordata is the modal layer in our application. Code data persist data permanently on the local disk. Core data manages and object graph. We use Core Data to save the applications permanent data for offline use to cash temporary data and to add the undo and redo functionality to our app on a single device. Other use cases. At the undo and redo the functionalities. Cash temporary data share will automatically sync data between multiple devices using CloudKit. What is an object graph? You may wonder what an object graph that core data manages is an object graph is nothing more than a collection of objects that are connected. For example, let's imagine that we created a movie application that stores the recent top box office movies. Now, if you think about the models in this app, obviously, there will be some type of model that represents the movie itself, but there will also be other models that describe the genres and the actors. As you can see, these objects or entities we call them encode data could connect to each other. This relationship can be one way or two way directional and core data basically takes care of keeping these relationships. Moreover, in a more complex scenario, this application could have a feature to filter out some kind of movies by genres or actors. The core data framework excels at managing complex object graphs. Not only that, but it also offers a powerful interface for searching object graphs that IT managers. But chordata is much more than that. So what chordata is not? First of all, chordata is not a database. As I said before, chordata is not a database, but rather an interface or bridge to it. Apple platforms provide three different storage solutions that core data supports by default, these disk-based stores are the following. Xml, binary, and SQLite. The most used and the most common core data on disk store is the SQLite. That's what most iOS app developer uses. C. Corps data provides abstractions that allow developers to interact with the model layer and the on-disk storage. That said, developers do not need to deal with the under the hood database directly. Plus, it adds a wide range of additional features. To understand how the core data framework operates, we need to get familiar with the Core Data stack. So let's take a look at this core data stack. Shall we call data stack persistent container. An instance of persistent container sets up the model, context and still coordinator all at once. Managed object model. An instance of managed object model represents your apps model file describing your appetites, properties and relationships. Managed object context. An instance of managed object context tracks changes to instances of your apps types. Persistent store coordinator. An instance of persistent store coordinator saves and fetches instances of your apps types from stalls. In a nutshell, this is the essence of the Core Data stack that every developer should know. As you can see, chordata is the go-to solution for storing data on Apple devices, and it should be your first choice as well. You know, the Core Data Framework provides us impressive performance and abroad set of features. While doing it, the framework also manages the entire model layer of our app and handles persistence on the device's storage disk. All right, enough with the talk. We will get familiar with the Xcode's Core Data project template in the rest of the lesson. To do that, first, open the project in code and select the devote data model file on the project navigator. As I show you. Then Xcode will open the object model editor for us. In the middle pane of this editor, you will find a pre-made entity called item. By clicking on its name, we can select it. Then pay attention to the right pane. There are three sections, namely attributes, relationships, and lastly, fetched properties. In this tutorial, we are going to focus solely on the entities attributes. As you can notice, the item entity has only one attribute. It's name is timestamp and its type is date. To add a new attribute to it, we need to click on the plus button. As I show you. To rename it, we need to click on the attribute and enter the following task. Then we have to choose a type from the drop-down menu, select the string type, and we are done here. You have just learned how to add a new attribute to a Core Data entity. The default window in the XC data model file is the table editor. But we can switch from this table editor to the graph editor using the toggle in the bottom menu bar of Xcode. Let's do it and take a brief look at the new graph editor. As you can see. There's only one card in the center of this pane containing the item entity. This object graph editor allows us to edit the entities and their relationships to each other visually. Later on in this masterclass, we will see how this works, but we don't need it for this project, so we can switch to the table editor. Next. So far, it was incredibly easy. However, we should learn about what's going on under the hood. And before we go on, I have to confess something to you. The persistence swift file and the devote XC data model files aren't real data model files, but they fall into the data model and storage category. That's why I told you to put them into the model folder. Okay. The truth be told, when we start a project using Xcode's Core Data project template, then Xcode sets up not only the previously mentioned persistence and data model graph files that the real model file with the class as well. However, this model file is hidden by default on purpose, you know, Xcode tries to do the heavy lifting work for us. And for starters, this could be very convenient. But we are here to learn how cold data works. So we need to deep dive into this framework. So back to the topic of core data's model file. You should know that provides us a building code generation feature. And I'm going to show you how it works in a sec. But first, we need to open the inspectors pane on the right. Please navigate to the top right corner of the window and activate the inspectors pain. As I show you, the fourth menu item is the data model inspector. Make sure that this is the active one. Here you can see a class section on the pain. And what's important here is the code generation drop-down menu. The default option is the class definition. It means that Xcode will watch every change on the entity editor and it will auto-generate and update the class definition for us. As I told you, this class file is hidden by default, but it is not mandatory at all since we have other options to deal with core data as well. Click on the drop-down menu and take a look at the other options. The top one is manual code generation, cheese manual slash non to edit the properties in your managed object subclass. For example, to alter access modifiers and to add additional convenience methods or business logic. With manual core data doesn't generate files to support your class. You have to create and maintain your class manually, including its properties. Core data then locates these files using the valleys you supply in the class name and module fields. Basically, we can do whatever we want, but we need to have the required knowledge to create and modify a model class. The benefit of using this option is that we have total control over the data model class and its properties. The default option is the class definition. In this case, Xcode will generate and update the model class from the entity. Choose this option when you don't need to edit the properties or functionality of the managed object subclass and properties files that core data generates for you. These files regenerate whenever the related entity changes in the data model. Also, these files could not be edited by purpose. The generated source code doesn't appear in your projects source list. Xcode produces the class and properties files as part of the build process and places them in your projects build directory. It's a very convenient way to work with core data. But we have no control over the auto-generated data class. Since we don't have access to this class file directly, That's why we don't see it in the project navigator. Finally, the last option for us to choose is the category slash extension, cheese category slash extension to add logic to the managed object subclass option to add additional convenience methods or business logic inside your managed object subclass. With the category slash extension option, you take full control of the class file while automatically generating the properties file to keep it up-to-date with the modal editor. It's up to you to create and maintain your class manually. It provides an in-between feature for us. By choosing this option, chordata will generate two files to support the data model, a class file and a properties file. It's a great option for some developers who want to extend the class with more features. But enough with the talk. Let's see how this works in action. First of all, make sure that the class definition is the selected option. It's because what we're going to do is just for demonstration purposes. Alright, follow me closely. Please. Navigate to the editor menu on the main toolbar. Then select the create NS managed object subclass many. A new window will pop up where we can select a data model. Yep, we have only one data model in this project. Click on the Next button as I do. Then we have to select an entity from the list. There is nothing complicated here since we have only one entity in this project. Click on the Next button again. Now we need to tell Xcode where we want to save the generated files. Technically, the best place to put these files is the model folder. Since we will only look at their code and won't use these files, we can leave them in the projects root. Splendid. As you can notice, two files are generated for us, a Core Data class and a Core Data properties files. First, we need to select the Data class file. This core data class file declares the class as a subclass of NSManagedObject. Core Data specify the item class that we'll use to create instances of our entities. Nothing fancy here, so we can jump to the properties file. Let's do it. Nice. The properties file declares an item extension to hold the NS managed properties representing any available attributes and relationships. Moreover, it can declare their accesses and other helper functionality for fetching instances of this type. As you can see, there are the timestamp and the task properties that we added not so long ago using the table editor. I hope everything is clear now after showing you how to create this data model class and its extension, use this feature carefully when you want to switch from auto code generation to manual. In this tutorial, I want to teach you how to use the default Xcode's Core Data project template. That's why we don't need to deal manually with the data class and its extension. In another core data tutorial, I will show you how to create a Core Data project from scratch and create and update these files manually. Having said that, select both of these files and delete them as I show you. It's done. Great job so far. Now it's time to get familiar with the persistence file. Shall we first select the persistence file and take a look at the pre-made code. Don't be scared. It has only four major sections and a persistence controller wraps all the code. This persistence controller is our starter point. Take your time to go through the whole code before we go on. Are you ready to move on? Awesome. First things first, we're going to clean up this template file and go through each section of it. But before starting, select all the long comments and delete them as I do, it will make the code not only shorter, but more eligible as well. Are you done? Nice. It's much better now, in my opinion. Now let's analyze and dissect this code, shall we? We can see in this code persistence controller that there are two essential properties declared within initialization. Besides that, there is a static preview variable as well. To be honest, I find the order of this section a little bit messy. That's why we will clean it up a little bit. At the top, there is a property called shed, which is an instance of persistence controller. Now for clarity, let's add a new comment marketer it enter, new comment. Mark. First persistent controller. It's a singleton for our entire app to use. As you already know, an instance of persistent controller sets up the model, context and store coordinator all at once. All right, now select the whole block of code of the preview and cut it out to the clipboard. By doing that, we can see the next important thing. It's the persistent container property. Let's add a new comment to it as well. Enter, new comment. Mark. Second, persistent container. It's the storage property for core data. Using persistent container is the preferred way to initialize our core data stack and load our core data model later. Nice. After covering these two properties importance, we can jump to the next section where we initialize the Core Data stack. But first, let's add a new comment to this section as well. Enter. New comment, Mark, fed initialization, then load the persistent store. We start by referring the persistent container to our core data storage called devote. The in-memory store part of that code is important because when we configure Core Data to save the information into memory rather than desk. It means that all the changes you make get thrown away when your program ends. What you also need to know about the in-memory store is the following. Core data provides an in-memory persistent store and three disk-based persistence tools. These disk-based stores are the following. Xml, binary, and SQLite. The most used and most common on disk or Datastore is the SQLite. That's what most iOS app developers use. So with this in memory conditional state, we can access the non-distinct storage. It's perfect for unit testing and for using it in the Swift UI preview. In this scenario, we need to provide a different file URL path for this purpose. Finally, we load the persistent store using basic error handling. And depending on if the in-memory is true or false, we can get access to the content of either the temporary or the disk SQLite store. And here goes the last part of this code, the preview, navigate to the end of the file and mark a new section there. Enter, new comment. Mark. Fourth, preview. After that, paste the code snippet from the clipboard as I do. It's a test configuration for solely Swift UI privies. Do you see how we switch from the default disk based datastore to the in-memory store by the tree value at the beginning. With that, we can set up and use any sample data in the Swift UI preview. We set up the sample data by using the for each loop, ten dummy items with the date timestamp that we can see on the preview. With the D try-catch, we save this sample data to the in-memory store. By the way, using the in-memory store for providing sample data to the preview is totally optional but highly recommended. Excellent. I hope that this was clear so far so we can move on. Up to this point. We have discussed the importance of the data model, the entity, and how to set up a persistent container, which is the Olin one gateway to Core Data Storage. Now, we need to talk about how we can access the data in our project after setting up the core data model and storage. To do that, we need to open the devote up file. At the top. Xcode generated a new instance of the persistence controller that was previously declared in the persistence file, as we have just talked about it. As you can notice, Xcode added this persistence controller property to the app structure via the environment modifier. This managed object context key in the environment is designed to store our active core data managed object context. In a nutshell, with that single line of code, the managed object context is injected for the core data container in the whole Swift UI app hierarchy, and it's all child views. Okay, dokey. To wrap up what we got so far from Xcode's Core Data project template. First, we got the core data model with a powerful editor. Second, we got the necessary persistent container setup fed the managed object context was injected into the initial app views environment using the managedObjectContext key. Now we can cover the last piece of the puzzle on how to use core data. To do that, open the content view file from the project navigator. As I do in this file, Xcode provides sample code to create, read and delete example data. But before we analyze this code, we should clean it up. That said, navigate to the section where two functions are declared. There, we can delete the multi-line comments so they can't disturb us. So far so good. Now scroll back to the top and enter a new comment Mark property. Then New Comment fetching data. Now hold on a sec and let's discuss this block of code. Shall we? Since we have already injected our managed object context into the swift UI environment, therefore, we can hear at an at environment property to content view to read the managed object context right out. Keep in mind that this shared context is required for saving, deleting and some other tasks. Next, fetch requests allow us to load core data results that match the specific criteria we specify. And swift UI combine those results directly to user interface elements. The app fetch request property wrapper could potentially have four parameters, such an entity, a sort descriptor, a predicate, and an animation parameter. One. The entity is what we want to query to. The sort descriptor determines the order in which results are returned. Three, with the predicate, we can filter the data four. And finally, the animation is used for any changes to the Fetched Results. Xcode's default core data template uses only the sort descriptors and the animation. So we started this extended code with a complex fetch request property wrapper. And we end it with a new items property that holds all items in the fetch result. With this property, we can fill up the list using the for each loop. Alright, that's all about these essential properties. So we can move on. Next. We are going to insert a new coding block between the properties and the body sections. Enter new comment, Mark function. After that, please navigate back to the functions and cut both of them to the clipboard as I do. Now, we can paste these functions to its new place. What we're doing now is not mandatory, but I prefer functions keeping between the properties and body sections. Of course, it's up to you to decide to follow this practice or don't. Finally, we can add a new comment for the body as well. Just one more thing before we finish up the code preparation. Please navigate back to the end of the main struct and cut out the date formatter computed property to the clipboard. As I show you, I think that we should store this formatter in a different place. That said, select the utility folder. And let's create a new swift file. Give it the name constant, and save this file. After that, we need to import the swift UI framework and add some comments to separate the different code blocks from each other. Enter new comment, mock formatter, then place the date formatter here from the clipboard. Of course, now we must remove the private key before the item formatter to make it accessible everywhere in the project. Great. Now a two new comments after it. Enter, new comment, mock UI, then enter the last comment, mock UX. And that's it for this lecture. Wrapping up. In this tutorial, we learned that the swift UIs integration with Core Data is quite opinionated and straightforward. First, we must create the core data container once when the app starts. Second, we must inject its managed object context into the environment. Third, then perform the fetch request directly there. Here are the full specific features that will help you see what I mean. Nsmanagedobject conforms to the observable object protocol, which means we can bind any object to part of our user interface. There's a managed object context key in the environment designed to store our active core data managed object context. Xcode's template then injects that context into the initial content view. There's that fetch request property wrapper that uses the environments managed object context to perform fetch requests. So we create a managed object context when the app launches, attach it to the environment for our views, then use it fetch request to load data for the app to use. We learned how called data works in general. And we also got familiar with Xcode, generated core data project template and its files. Finally, we cleaned up and restructured our code for the upcoming coding lessons. Having said that, see you at the class. 4. Let's create a basic to-do app from Xcode's Core Data template: In this class, we're going to develop a fully functional to-do list application from Xcode's Core Data project template. You will see how far we can go with Chordata and few lines of code using the swift UI framework. This to-do list app has all the basic functionalities like adding a new task item or deleting an old one. Not only that, at the end of the class, we will develop a safety feature for it as well. So users cannot save an empty task. That said, by the end of this tutorial, we will put together something useful. All right, without further ado, let's launch Xcode and start coding. Okay? First things first, select the devote XC data model file on the project navigator. We start by adding some new attributes to the item entity. Ensure that the item entity is selected in the middle pane. Then add a new attribute to it by clicking on the big plus button. Give it the name ID. Then select the year you i0 for its type from the drop down menu as I show you next. Lastly, add another attribute to the item entity, give it the name completion, then select a boolean for its type. As I do with that, our class got all properties and we won't need to touch them in the future. Easy-peasy persistence. Now we can jump to the persistence file and make some modifications there. First, navigate to the previous section. And let's make some changes in that for each elite, for I in 0, less than five. Then place your cursor after the timestamp and enter the following code. New item dot task equals sample task number i, then new item.com equals false. Finally, enter new item dot IE equals U, U ID. We have just updated the sample data with the new properties in the preview with this new code. So we can conveniently test and build up the layout of this application. Layout design. So far so good. Now I can the content view file and navigate to the body section. Here we first need to embed the ListView into a new vertical stack container. So let's do it. The stack. Then mark the end of these views with new comments, new comment, end of the V stack. Then New Comment end of the toolbar. After that, select the whole toolbar and add it to the vertical stack. As I show you, super after all this prep work, navigate the kasa to the property section and enter the following code. At state law, task string equals empty string. We have just created a new string property for the task and initialized it with an empty string. With that, we can create a new text field and use this property to hold the valley that uses enter. To do that, first, we need to go back to the stack and enter this code before the list view. The stack, spacing 16, then new comment and a V stack. New modifier padding. We're going to add to this vertical stack and new text field with a button. Now, enter TextField. New task. Text. Dollar sign, task. Padding, background, color, UIColor, system gray, six, corner radius 10. Nice. The new text field is done. Now after this, we need to add a new Save button. Enter the following code. Button. Action. Add item, label, spacer, text, save, spacer. Putting. Fund. Headline, foreground color, white, background, color, pink, corner radius 10. Now scroll down to the end of the outer vertical stack. Enter this code before the toolbar modifier. Navigation bar title. Daily tasks. Display mode, large, DC. How easy it was to create a decent design with the Swift UI framework. Alright, the new form is done. Now it's time to modify the addItem function. So when a user taps on the button, then it will save a new task item. Please scroll up to this function and add these lines of CO2 it new item dot task equals task. Then new item.com equals false. Finally, enter new item, dot id equals you Udi. This code is almost identical to the code that we have added to the persistence files preview. This code works as it should do. However, to see what's happening, we need to make it visible by modifying the layout of the list view as well. Scroll down to the text view inside the for each loop in the list and embedded into a new vertical stack. Then enter new comment, list item. Then at these modifiers to the text view fund, footnote, foreground color. Gray. This code will make the timestamp not so prominent. After that, we will add a new TextView before this timestamp, enter text. Item dot, task, double question marks, empty string, fund, headline, font-weight, bold. Now we need to add an alignment attribute to the vertical stack. The stack alignment leading. With that code, the layout design is done, as you can see in the preview window. It's time to test the application using the simulator. Let's build and run the project. Now before we test the app, we need to make the keyboard visible though to the top toolbar and under the input and output, many navigate to the keyboard section and select the Toggle Software Keyboard option. As I show you, it will make visible the devices keyboard. When we tap on the TextField, see how this works. After that, we can enter some sample tasks and try to save them by clicking on the button. Now, if you do this test carefully, then you should notice two problems. When we save the task item. Content in the text field is still there. The solution for that is to dismiss the previously saved content and clear the TextField. The second problem with this app that we can save EMT task items as well. To do that, first, make the text field empty, then click on the Save button a couple of times. Do you see the empty task items in the list view with their timestamps? Yes, I'm talking about this problem. The third problem is that the keyboard should be dismissed each time when a new task item is saved to persistent storage. So that's all the problems that we need to solve in the rest of the class. By the way, our code works as it should do. Yet, we must take care of the user experience as well and prevent this kind of unwanted situation. User experience. Jump back to Xcode and scroll up to the properties section as I do to check whether the text field is empty or isn't, we will create a special computed property. If you are a beginner developer, then pay attention to this code because this will reveal the power of computed properties for sure. Enter private, var, It's button disabled. Dual, task is empty. This computed property will not only check the emptiness status of the TextField, but it will hold the true or false Boolean value according to it. How elegant is this code? I hope you like it. Now, back to work. So having this true or false Valley, we can disable the Save button and prevent it from cooling the addItem function. And we can do it by using a less known modifier. First, navigate to the end of the button and add this new modifier to it. Disabled. It's button disabled. We made it the beauty in this code that we didn't have to use an explicit if else conditional statement to accomplish this. How cool is that? We can test how this code works by running the simulator. So let's do it. Alright, the text field is empty by default. Now try to save and add an empty task by clicking on the Save button a few times. See, it's impossible because the button is disabled. The only problem with that, that we cannot see that the button is disabled. That's why we need to add some visual feedback to the users. The good news is that we can do that in advance by changing the buttons color to something different when it's disabled. Having said that, jumped back to Xcode and let's modify the buttons background color with this code. Background is button disabled. Question mark, color, dark gray, colon, color dot pink. As you can, the background color in the preview has already changed from pink to gray since this is the default state. Dismissing keyboard. The final thing that we can do to improve the overall user experience is to dismiss the keyboard each time when a new task item is saved. To do that, first, we need to create a new extension. Select the extension folder in the project navigator. And let's create a new swift file. Give it the name hide keyboard extension, and save it. Now we need to import the swift UI framework. Great job. So far. After that, we're going to declare a conditional statement, enter the following code. Hash. If can import UIKit hash. And if statements, the code inside this condition will only run when we can import the UIKit framework. Let's continue with the following code. Extension, view, funk, height keyboard. You application, dot, shed, dot, send action. Hash, selector. Uiresponder, dot resignFirstResponder to nil. From nil. For nil. Pay attention to the resignFirstResponder in this hide keyboard function. It will dismiss the keyboard when we decide to run the function. You know what? Up to this point, swift UI is still a young framework and unfortunately, it does not have the capability to dismiss the keyboard directly. I'm pretty sure that this will change in the near future. Until that we have to get helped out from the UIKit framework. Our new function is ready to use. So jump back to the content view file and navigate to the addItem function as I do. Here, we need to do two things. First, we will empty the text field by adding this code to this function at the end of it. Task equals empty string. It's quite self-explanatory so that we can move on to the final task. It will run that the height keyboard function, Enter, hide keyboard. Excellent work. Just one more thing. Before we call it a day, we need to modify the tool bar slightly. Please scroll down to it and change the Edit buttons placement from leading, trailing, as I show you. After that, we just need to get rid of the plus button entirely from the toolbar. Perfect. Our project doesn't need this code from the core data template anymore. Now let's build and run the project in the simulator, or even better on a real device. After the app launch, Let's test out the new functionalities that we had just developed a moment ago. Shall we enter some comments in the text field and try to save them? Okay, That's work. Did you see when the button's color changed from greater pink? As soon as we entered some characters into the text field. The next thing that had happened when we tap the Save button is the TextField became empty again. See, improving the overall user experience with these small features wasn't particularly hard. It's especially true if you know how to dismiss the keyboard using Swift UI older companion, the UIKit framework. I hope you enjoyed this practical tutorial and you appreciate that I showed you how to change the default core data project template to a working to-do list. Also get excited because in the following lectures, we will start making an extraordinary application from this really basic app until then, happy coding. 5. Let's develop a stellar app design: In this lesson, we will lay down the foundation of the layout and the design, mainly the appearance of the background and the list view. By the end of the class, our app will look much better than before. But not only that, this prep work is quite necessary for the upcoming lectures. Alright. Without further ado, launch Xcode and start coding along with me. I opened the content view file and navigate the kasa to the outer vertical stack container. Now, we need to embed this view into uneasy stack container Command Plus click on the view name and select the embed in Z stat container. As usual, it will do the job. However, it will mess up the comments a little bit. That's why scroll down and swap the new closing bracket with the other one. As I show you. Then add a new comment to it. Enter new comment end of the stack. After that, select the navigation bar title and the toolbar modifiers and add them to the z stack. Great job so far. This new container plays a significant role in the layout design. Next, we will support the iPad devices by adding a new modifier to the Navigation View. Enter the following code. Navigation view style, stack Navigation View style. Sepah. This guide will make sure that the navigation view will only show a single column view at a time. You can also notice how the layout changed in the preview window as well. Now, it's time to add a new background to this view, since we will use this specific linear gradient multiple times in this project here and there. Therefore, it's worth creating a reasonable property for that purpose. First opened the constant file, then let's create a new computed property at the user interface section. Enter var, background gradient, linear gradient. Return, linear gradient. Gradient, gradient, colors, color dot pink, color dark blue. Start point, leading, endpoint, bottom trailing. Great. Now switch back to the content view file and let's add a new background to the z stack. Background. Background gradient, ignore safe area. As you can see, there is a new linear gradient background. After this, we need to work on the list to achieve the desired design. First at this new modifier to the list view, list-style, inset, grouped list-style. Almost perfect. But now we must remove the background color from this new list. Look. To do that, we need to wrap this specific code into a new on a pay modifier, navigate to the end of the z stack and enter on a pair. Ui TableView. Appearance, background-color equals UI, color. Clear. This code will set the background color of the undelivered table view to clear. That means it will be transparent and it will reveal the linear gradient color. Finally, we can make this list pocket by adding a nice shadow to the list view. Shadow, color, color, red, green, blue, 00 dot three, radius 12. Can you notice the difference? It's much better now. Now we just need to add two other modifiers to the list. Enter, padding, vertical, 0, frame, max width, 640. This code will remove the default vertical padding and maximize the list on iPad devices. Splendid. The last task to do is to add the background image on top of this linear gradient background. To do that, we need to create a reasonable Swift UIView with a single image in it. That said, select the view folder and let's create a new file for it. Give it the name background, image, view, and save it to its destination. White. After that, we're going to replace the default placeholder text with a new image view. Enter this code. Image, rocket. Anti-alias, true. Resizable. Scale to fill. Ignore safe area. All. Please pay attention to the fill view modifier. It makes sure that this image will scale to fill its parent view no matter what, while maintaining its aspect ratio. So it won't be distorted. Next, by the way, this anti-alias modifier will keep the edges of the image smooth when it is scaled up or down respectively. All that said, we can add this image to the content view. So let's do it. Jump back to the content view and insert a new background modifier between the toolbar and the background. Enter background, background, image view. Awesome. We're going to finish up this short class by debugging the application on the Canvas. Did you know before that besides the live preview feature, there is a debug preview feature. Please click on the Play button with the secondary mouse button and select the debug preview option. As I show you, this feature is handy when we use it combined with the print method. So it's worth knowing it, in my opinion. Now we can enter some new tasks. Then save them. Congratulations. It works without any glitches as it should do. The next lecture will be an important one because we will move the text field and the save button to a new dedicated view. Until then, happy coding and see you at the class. 6. Create a new entry form for the task item: This lecture is an exciting one and you will learn some practical Upbuilding techniques. As you can see in this demo, there is no text field and save button on the iPhone screen anymore. We're going to replace them with a new at Task button in the top area. And when we tack on this button and new full-screen view shows up with the previously mentioned TextField and save button. Apps layout gets more complex with multiple layers, but it's worth working on it. Having said that by the end of this class, this app will be more polished than it was before. Okay, without further ado, let's launch Xcode and start coding. First of all, we will start by creating a dedicated Swift UI file for the new task form. Select the view folder as the destination, and let's create a new file. Give it the name new task item view and save it as usual. Then at this new view modifier to the previous background, color gray edges ignoring safe area. All this code will emulate the full-screen environment below the new view that we will build up right now. Don't worry that this gray background hasn't filled up the entire screen. It will work seen after we add an expandable view in the body. So let's do it. To do that, we need to replace the placeholder text view with a new vertical stacked container. Enter the stack. Spacer. New comment end of the V stack. Now I open the content view file and go to the body section. Here we need to select the inner vertical stack container with the text field and the save button. Then cut them out to the clipboard as I do. After that, jump back to the new task item view and paste the code from the clipboard into the vertical stack container after the spacer. Our code now is broken and it won't be compiled, but don't be disturbed by that. We will fix it. Seen. Switch back to the content view file and go to the top where you can find that is button disabled property. First, we must cut it to the clipboard and then we need to paste it into the new task item view as I show you. So far so good. But we are not done yet. Switch back to the content view file a third time. Here we need to select and cut out the whole at item a function to the clipboard. Then create a new code block in the new task item view and paste this function into it as well. Enter new comment, mock function. Kite fixing. Great. After all this prep work, we can finally fix every broken part and make our code work again. If you take a brief look at the error messages, then you get a good picture of what's wrong with this code. First, we have to add that view context to this file. Second, we need to create a new task property as well. And by providing these missing parts, we can make the compiler happy again. So let's fix this code. Navigate to the property section and enter the following code. At environment. Managed object context, private, var, view context. With this code, We get access to the managed object context, which is required to make them addItem function work. Next, let's create a new task property that will hold the value of the text field. Enter at state private, var, task string equals empty string. And here it goes, the error messages are gone. We can rebuild the project and refresh the preview window to see what's going on. Ops, it's not quite there. We still have to work on it to achieve the desired look. So let's carry on. First, scroll down to the body section. Here we need to add a couple of new modifiers to the inner vertical stack view. Enter the following code. Padding, horizontal, padding, vertical 20. Then let's continue with this code. Background, color, white, corner radius 16. It's much better now. After all this code, let's add two new modifiers to this view. Shadow, color, color red, 0, green, 0, please 0, 0 points 65, radius 24. Then enter this one. Frame. Max width 640. And last but not least, navigate to the outer V stack and add some padding to it as well. Enter padding. With this code. The general layout of this view is done. Now, we can focus on the small details that make our app even more spectacular. Polishing the details. First and foremost, let's add some new modifiers to the text field. Enter foreground color, pink. Font. System, size, 24, weight, bold, design, rounded. Awesome. The text fields design is done. We can continue with the Save button. Shall we add the following code to the buttons? Text view, font, system. Size 24. Weight, bold, design, rounded. Now jump to the end of the button view. Here we can delete the font modifier because we don't need it anymore. And finally, let's modify the buttons. Background color is button disabled, color blue. With all of this code, our design is done. Great job. Now let's see how we can implement it into the main view layout updates. To do that, first, we need to switch back to the content view file. Then we will create a new property. State, private, var, shown you task item, boolean equals false. With this new property, we can store the actual state of the new task item view. Next, we need to prepare the layout for the new code. First, we will define and Mach all sections with comments. Navigate the costs are too busy. Stack and insert a new comment before the V stack. Enter new comment, mock main view, then enter more comments in the following place. In the V stack. New comment, mock header. Then New Comment, mock, new task button. After that new comment, mock tasks. And finally at the end of the z stack and to this one, new command, mock, new task item. All right, We continue with a new header section, enter spacer, minute length 80. As you can see in the preview, this code will create some space at the top of the view. Say the design can breathe custom button. We will create a new button. Enter this code. Button. Action. Shown you task item equals true. Label. Image, system name, plus dot, circle. Font. System size, fatty, weight, semi bold. Design, rounded. Text. New task. Font. System. Size, 24. Weight. Bold. Design, rounded. Foreground color, white. Padding. Horizontal, 20, padding, vertical, 15. Background. Linear gradient. Gradient, gradient, colors, color, dot. Pink, color, dot blue, start point, leading, endpoint, trailing. Clips shape. Capsule. Shadow, color, color, red, green, blue, 0.250, radius eight X 0, Y, four. As you can see in the preview, the custom button is done. Do you like it? I hope so. After adding this new button to the main view, we can finally inset the new task item view. Scroll down to its section and enter the following conditional statement. If shown you task item, new task item view. When the show new task item property becomes true, then it will display the new task item view on top of the main container. Now let's start the live preview and see how this works in action. Click on the new task button and see what's happening. The new task item view shows up on top of the main view. However, we couldn't dismiss this view at all and we must fix this problem asap. Another thing that we need to solve is the new item view and the main container is not separated from each other visually. We will find a solution for that as well. Blank view. We start with fixing the design by creating a special view. Let's create a new swift UI view as usual. Then give it the following name. Blank view and save it. Then first things first, replace the placeholder text view with this code. Enter. Stack. Spacer. Frame, minute with 0. Max width infinity. Minute height 0, max height infinity. Alignment, center. Background, color, dot black. Opacity, 0 points five edges ignoring safe area. All. It's completed. As you can see in the preview window, we have just created a semi-transparent view that fills the whole screen. This will be the layer between the main view and the new task item view. To make it happen, first, we need to switch back to the content view file. And at this new blank view into the conditional statement, enter blank view. With that, the visual separation is done. Now we will add a new tap gesture modifier to this view so users can dismiss it. Enter on tap gesture. With animation, showing you task item equals false. Now let's test this code how it works in the live preview. Can you see the difference between the old design and the new one underneath the new task item view, a semi-transparent blank view makes this design much better. Moreover, when we tack on the blank view, it will disappear with a smooth animation. Let's try it out a couple of times, shall we? It works without any problem. How cool is that? Dismiss with binding? After improving the user experience with this new feature, we can now focus on the new task item view. Our new goal is to dismiss this view each time when we save a new task item to the persistent store. To do that, we need to make the content view and this view to communicate to each other. First, open the new task item view file, and let's create a new property for that. Enter. At finding var is showing Boolean. We have just created a new property with a binding property wrapper and without any initial value. Now I'll preview is broken because of the missing argument. To fix it, scroll down and let's add a new constant with some Valley to hit Enter. New task item view is showing constant, true. This constant will make the preview work again. Thus, we're still not done here. Navigate to the Add Item function and enter this code after the hide keyboard is showing equals false. This guide ensures that each time we save a new task item to the store, we change the value of this is showing a property to false. We need to pass this valley to the content view file and dismiss or show the new task item view accordingly. That's why jumped back to the content view file and ensure that the new task item view gets this parameter in set this parameter to it. As I show you, new task item view is showing dollar sign, shown you task item. With this code, we can bind and pass through that true or false value of the share new task item parameter. Testing. To see how this code works, we can start the live preview and test this functionality by saving some new task items. So let's do it right now. After entering some content into the text field, we can save it and see whether the new task item view is dismissed or isn't. Let's check it out. As you can see, it works without any glitches. How fantastic is that our personal task management application gets better and better after each lesson. I hope that you have liked developing this project so far. I can tell you that we will add more exciting features to this core data in the upcoming lectures. That's being said, Happy coding and see you at the class. 7. Let's develop a custom header: In this swift UI class, we're going to develop a custom header with a new feature. As you can see in the demo, the large title is in the same line as the header sections buttons. And besides the customer edit button, there is a light and dark mode switch button. So the app users can toggle the apps appearance as they wish, no matter how their phones appearance is set. Having said that, by the end of this lesson, we will make the today's list and the new task item form to support both the light, the dark appearances. Are you eager to develop this new feature and add more value to this application? I hope so. That's why Let's open Xcode and start coding along with me. Okay? First things first, navigate to the end of the z stack. Since we will create a new header, therefore, we don't need the toolbar anymore. Select the whole toolbar modifier and deleted. As I show you. Next, we could delete the navigation bar title too, but I would like to introduce you to a new modifier. It turned out that we can hide the navigation bar in a specific view with a dedicated modifier. Enter the following code. Navigation bar hidden. True. It's as simple as that custom header. All right, After this prep work, we can start creating the custom header for this application. First, navigate to the header section, and let's add a new horizontal stack container to it. Enter each stack. Spacing. Ten. New command, end of the stack. Padding, foreground color white. After that, let's mark the main sections of this header with new comments. Enter, new comment, title. New comment, edit button, new command, appearance button. Title. We will start with adding a new title to this header. Enter the following code. Text. Devote. Font. System. Large title, design, rounded, font weight, heavy. Padding. Leading. For spacer. The look of the new title is much better than Swift UI is default title with nice dialing edit button. Next, we will continue with creating a custom edit button. Enter the following code. Edit button. Font. System. Size 16. Wait. Semi bold, design, rounded. Padding. Horizontal, 10, frame, minimum width, 70, minimum height, 24. Background, capsule, stroke, color, white. Line width. Too. Great. With this code, we have just developed an edit button with a custom design. We can finish up this header by adding a new appearance button to it. So let's do it right now. Appearance button. First, we will start with developing the design of this new button. Then we will develop the actual functionality for this feature. That being said, and to the following code. Button. Action, new command, toggle appearance. Label, image, system name, mean dot cycle. Resizable. Frame with 24, height, 24. Font. System. Title, designed rounded. And guess what we have done with developing the design of this new header. It's time to add functionality for the new appearance button, light and dark mode. Since we want to store the actual appearance permanently, That's why it's a good choice to use Swift GUIs app storage for it. Navigate to the top, and let's create a new property to do this job for us, shall we enter the following code? At App storage is dark mode, private, var is dark mode. Boolean equals false. The default appearance will be the light mode for this application. And we also decided to store this valley by using that with dark mode, a key in the Swift UIs UserDefaults. After that, we need to navigate to the appearance button and add a new action to it. Enter is dark mode, dot toggle. Now go to the buttons image and let's modify it with this code. Image, system name. It's dark mode. Question mock, mean dot cycle, dot fill, colon, mean dot cycle. And we are done with developing the appearance switcher. To see how this code works fast, we need to stop the live preview. So let's do that. When the live preview is running, click on the Appearance button as I show you. As you can see, the buttons image switched from the secular mean to second fill image. Now we just need to set the applications appearance separately from the global devices appearance. Preferred color scheme. First, I open the devote app file as I do. Then we need to declare the property again. So when we start the application, it will load the actual value of the appearance from the users defaults enter the following code. At App storage. Is dark mode, var is dark mode. Boolean equals false. Alright, after adding this property, finally, we can set the apps appearance with a new modifier, data the content view, and add this new modifier to it. Preferred color scheme is dark mode, question mark, colon, light. This code will set the preferred color scheme of this application independently regardless of what appearance is set globally on the device. To test how this preferred color scheme works, we need to build and run the project. So let's do it testing. Firstly, when the devote app launches, we can see the default light mode on the screen. Then we can switch from this light motor dark mode by tapping on the appearance button. As I show you, you will see that the list view immediately switched from light to dark mode. No additional action and code is required from us. It seems to be working. But what will happen when we tack on the new task, but in yikes, It's not exactly what we want to see. You know, using the preferred color scheme is ideal for all Swift UI is built-in user interface elements. It will switch from one mode to another one automatically. But when it comes to any custom design, then we have to manage it manually. This is why we must work on this new task item component and little bit, not a big deal. Just follow along with me. Light and dark theme. That said, jump back to Xcode and open that new task item view file. As I do, We just need to make this custom components switch from light to dark mode and vice versa. First, we need to create a new property that will fetch the UserDefaults actual value. Enter this code. App storage is dark mode. Private, var is dark mode. Boolean equals false. Please ignore the false Valley. We added it to this property for initialization purposes. After this, scroll down to the body section. While looking at the preview window, we can find TVs that we need to prepare for theme switching. The first one is the text field. We're going to replace the background color with a new conditional modifier. Enter this code. Background is dark mode, question mark, color, UIColor. Tertiary system background. Colin, color, UIColor. Secondary system background. You may wonder why these background colors were chosen. I can tell you that I found these colors best suitable for this design. Of course, you can choose different colors from the system color palette as you wish. Next, finally, we need to modify the NRV stacks background color, replaced the white background with this new conditional modifier. Background. It's dark mode, question mark, color, UIColor, secondary system background, colon, color, white. It's done. Technically speaking, we use the ternary operator in both cases. And in case you are a beginner developer. As a reminder, to use the ternary operator, we need to write our condition fast, then a question mark and what should be used if the condition is true, then a colon followed by what should be used if the condition is false. I hope that you find this side note helpful. Back to development. The only thing we need to do now is to test how this code works when we toggle the apps appearance. Final test. Having said that, let's build and run the project either on a real device or in the simulator. As you can see in this lecture, we have developed a custom header section with a large custom title and two buttons. What's worth mentioning is the new appearance switch a feature. Firstly, you have learned how we can set the apps appearance using the preferred color scheme. With this, we can change the appearance separately from the global setting of the device. Secondly, we also learned that this automatic color theme switcher only works using Swift UI is built-in user interfaces. Then we need to support this feature manually each time we implement a custom component. Finally, to make this feature work, we decided to store and fetch the appearance using Swift UI users default with the app storage property wrapper. How cool this lecture was. I hope you enjoyed it and I'm glad to let you know that we will develop other exciting things in the next class. Until then, happy coding. 8. Improve the individual task item view: In this class, we're going to improve the design of the task item in the list. We will solely focus on creating this individual component. Besides that, we will learn how to customize the look and feel of a swift UI toggle. You know, similarly to button, Swift UI also lets developers customized toggles style. All we need to do is to implement the toggle style protocol and provide the customizations. By the end of this lesson, we will develop a custom checkbox component from Swift UIs toggle, Okey-dokey. Let's get down to business. After launching XCode, please select the view folder. And let's create a new swift UI file for the task item. Give it the name, list row item view, and save it as usual. Super. In this class, we're going to old school like in the old days of app development. Wink, wink. Since we weren't provide sample data for the individual task item, therefore, we don't need to have a preview. I know that's quite unusual in this masterclass because until now we always supported the preview. Yet I think that it's worth practicing developing the layout fully programmatically. It can sharpen your thinking and imagination as well. The full Swift UI, it was a common practice in the development workflow. That's why we can delete the preview block as I show you. Before we start creating the layout design. First, we need to prepare this component. To make this component what properly. Then we need to access the view context. Enter the following code. At environment, managed object context, var context. After that, we will need to create another property. Enter this code. At observed object, var item, item. You may wonder why we need this item property. You know, a typical core data application follows the crowd design idea. This crowd acronym stands for create, read, update, and delete programming concepts. Xcode's default core data project template is using only three of these crowd pattern. Until this point, we can create and save any new task items as we wish to the permanent store. We can also read and fetch all task items from this store and display them in a list view. Moreover, we can delete any task item which we want. Also, you know, that only one thing is missing to make this application well-rounded. Yes, you are right. The only feature that this app is lacking is the update operation. And we're going to develop this specific functionality by adding the completion feature with a toggle slash checkbox UI element. But to do that, we need to declare an item property that observes and saves all checkbox changes every time we toggle the checkbox from false to true or vice versa. This observed object will invalidate the view and it's Valley. To see how this works, we need to continue developing the layout. Task completion. Alright. The layout is quite simple. We will create a toggle element and inside it, we will insert the task item as its label. That said, replace the placeholder text with a new toggle element. Enter the following code. Toggle is on. Dollar sign, item completion, new comment, the end of the toggle. Then let's add a new label to it. Enter text, item, task, double question mark, empty string. Font. System. Title. To design, rounded font weight, heavy. Foreground, color, item, completion, question mark, color, pink, color, primary, padding, vertical, 12. Animation, default. As you can see, we use the conditional modifier in the foreground color so that users will get more visual hints about the task completion. When the toggle is on, it means that the task is done and the text will change from the system color to pink. It's not hard to read and imagine our design. In my opinion, the total UI element indicates whether the task item is completed or isn't. Next, the text label shows the name of the task itself, updates. The design of the new list row item is done. The only thing that we need to do is to add the update functionality to it. To do that, we need to add a specific modifier to this toggle element, enter this code. Onreceive. Item. Object will change, perform underscore in. If self dot view context dot has changes. Try question mark. Self dot view context dot save. Just hold on a sec and let's discuss how this code works. Shall we? First of all, this onreceive, the modifier consists of two parameters. And with these parts, it adds an action to perform each time when the view detects any change. So the first parameter is that the item object will change. It is a publisher to subscribe to. Every time there is a change, then it will run the given action. The second parameter is the action that is triggered each time when an event happens in the closure, we are trying to save the new valleys safely and update the store by doing that. In a nutshell, this is how this toggle works together with the cool data framework. I hope that everything is clear so far. We can test it and see how this code works in action code implementation. To do that, I can the content v file and navigate the kasa to the for each loop in the list view. As I show you. Here, we need to select the whole layout and deleted as I do. Then we can insert the new toggle component, enter the following code. List, row item, view, item, item. Great job so far. Now we can finally tested in the live preview. Let's start it and take a quick look at the new list row. Do you like it? Yeah, not bad at all. But you know what? We can do it even better. One thing that makes working with Swift UI especially enjoyable is the new features that Apples engineers are adding to it constantly. In the rest of the lecture, we will make the design outstanding from the crowd. Checkbox component. Fast. Please select the style folder from the project navigator pane. Then let's create a new swift UI file for this UI element. Give it the name Checkbox style and save it to this group. Now first things first, though to the previous section, replace the view with a new toggle element. Enter the following code. Toggle. Placeholder label is on constant, true. Padding. Preview layout. Size that fits. Splendid. Since we will develop a new style for Swift UI is toggle element. Therefore, the best way to use the preview is to insert a new toggle element with our custom style. Toggle style. Please pay attention to me because there is a specific formula for creating a custom toggles style. Just follow me step-by-step. First, we need to replace the view with a toggle style. Enter, checkbox style, toggle style. Nice. Now after that, we will replace the whole body part with a new body maker function. So let's do it. Function, make body configuration, configuration, return some view. With this code, we have just set up a new function that will create the body for the toggle element. You may wonder where this toggle style configuration, tight alias comes from. And by Option plus click on this configuration, we can get more information about it. Just click on that open in developer documentation, link and Xcode will open the documentation in a separate window. Now select that a toggle style configuration to read the full description of how this styling works. As you can notice, a toggle style has two properties. One of them is that is on the state. The other one is the label view. This is what we need to provide in order to make this toggle style operate correctly. Having said that, close the documentation window and let's continue coding. Enter the following code inside the function. Return h stack. New comment, the end of the H stack. This will be the main layout container. Now let's add a new image to it. Shall we enter? Image? System name? Configuration is on. Question mark, checkmark dot circle, dot fill, colon, circle. With this code, we have just created the checkmark image conditionally. To see how this works, we will add this half-baked toggle style to the view in the preview. Let's do it right now. Toggle element, toggle style, checkbook style. And there it goes. Do you see the new checkbox in the preview? We are almost done. Go back to the image view and add these new modifiers to make it even better. Foreground color, configuration is on question mark. Pink, colon, primary. Then fond, system, size, fatty weight, semi bold, design, rounded. As you can see, the shake of the checkbox image is more prominent now. Moreover, when it's on, then it becomes pink as well. Finally, we can add a new food on tap gesture modifier to it. This way, it can be turned on and off. Enter on tap gesture. Configuration is on. Toggle. Just one more thing before we call it a day, we need to provide a label view for this checkbox. Enter this code after the image view configuration. Label. Super-duper. Now if we change the constant value from tree to false, then we should see the off-state of this checkbox in the preview. See final task. Now, our very last task is to add this new toggle style to the toggle element in the list item row. I opened the list row item view file and add this new modifier to the toggle element. Enter, toggle, toggle style, checkbook style. Testing. To see how our new toggle style works in action, we need to build and run the project and boiler. This applications look and feel have been vastly improved by adding a completion checkbox to each individual task item in the list view. Now let's check on and check off some of the task items from the list. Shall we? What do you think about it? Do you like this new feature? I hope so. Sum up. In this class, we covered not only how we can add the update functionality to our application, but also how to create a custom toggles style. You know, in our code, we implemented the make body method, which is the requirement of the toggle style protocol. We also created an image view that displays a checkmark image or a sacral image depending on the status of the toggle. This is the way how we can customize the style of a toggle element. Last but not least, Use the checkbook style. We attach this new toggle style modifier to the toggle. Congratulations, you made great progress by finishing up this lecture. I hope you enjoyed it and you're eager to continue picking up new tricks and tips in the next class. Until then, happy coding. 9. Learn how to create a custom visual effect in SwiftUI: In this lecture, we're going to have some fun because we will create a stunning visual effect with Swift UI. Please take a brief look at this demo and watch how this visual effect works in action. To trigger this effect, first, we need to tackle maybe New Task button. As I show you, shortly after a new entry form appeared on the screen. What's new in this screen is the visual effect that makes the layer blood and vibrant behind this form view. With this, The Form View becomes visually separated from the main view. This visual effect makes the user experience more valuable because users can focus on only one thing to create a new task item. Not only it looks cool and it's also helpful, but it's smart to let switch from light to dark mode and try to notice the difference. Did you catch it? This visual effect looks noticeable differently in dark mode then enlight mode. It's darker and more vibrant. By the end of this class, our application will be much better with this new visual effect. Does it sound great? Then let's launch Xcode. Preface. All right, before we start coding, I think it's worth mentioning that there is a built-in visual effect in the UIKit framework. However, unfortunately, it hasn't been ported to the swift UI framework yet. Moreover, I find implementing this UI Kit visual effect into a swift UI project to be neither straightforward nor intuitive at all. But don't worry, I'm pretty sure that in the next big Swift UI update, Apple engineers will find a solution to add a visual effect to any swift UI view as a simple view modifier. Until then, I will show you how easy to create this visual effect manually. As you can remember, there is a blank, semi-transparent layer between the main view and the new task item view. This is what we will transform into a cool visual effect. Please open the the blank view of file as I show you to see how this visual effect looks in the preview while we're developing it. First, we need to add too familiar backgrounds to it in the preview. Go to the preview and let's add the first background to it. Enter blank view, background, background image. So far so good. Now let's add a linear gradient background underneath to it as well. Enter this code. Background. Background gradient. Ignore safe area. Oh, there it goes. After this prep work. Finally, we can see and test the visual effect in real time using the preview. How cool is that? But now, back to work. To make this visual effect reasonable, we need to create two properties for it. Enter the following code. Var background, color, color, var, background capacity, double. Now we have to fix the preview. Go to the preview and let's add the missing arguments for the parameters. Enter blank view, background-color, color, dot black, background, opacity 0.3. The era has gone in the preview. Now we need to make a quick detour and fix the code in that content view. I open the content view file and navigate to that, the blank view. Whereas a new error message from Xcode's precompiled. To eliminate this error, just click on the Fix button and let's add some information for the parameters. Enter blank view, background-color, color, dot black, background, opacity, 0.3. Great job. With these two properties, we will be able to choose any color with different transparency as we wish whenever we want. Next, we will continue developing the new visual effect. Jump back to the blank view file and let's replace the hard-coded information of the background and capacity modifiers. Let's start with the background modifier. Enter background, background color. Let's continue with the opacity modifier. Enter capacity, background capacity. It wasn't particularly hard so far, is it blend mode? Now, here comes the real deal. We're going to add two special modifiers to this transparent view. Enter the following code. Blend mode. When you enter the dot, then Xcode will provide us a drop-down menu with all possible options that we can choose from. If you're somewhat good at digital color mixing works in design software, then these given options could be familiar to you. For example, there is a darkened mode, a color band mode, a multiplayer mode, a luminosity mode, and so on. Please select the overlay color display mode from this list. As you can see in the preview, this designs, look, and feel are different due to this color blending modifier. We are almost there, but the fun part is just beginning. By the way, did you know that depending on the views, background, color, we can get a totally different result with this blend mode. And that we will do to create a different visual effect in the light mode then in the dark mode. To do that, first, we need to jump back to the content view file again. Here we will re-indent the code of the background modifier. We can wrap the code into a new line at each parameter, as I show you. Here it goes. Now, go to the background color and change this color conditionally. Enter. Blank view. Background color is dark mode. Question mark, color dot Black, Colin, color dot gray. Then let's continue with the capacity as well. Background opacity. It's dark mode. Question mark 0.3 colon 0.5. With this code, we will get different visual effects, either in light or in dark mode using the color blend modifier. Easy-peasy, isn't it? I hope so. Just one more thing before we call it a day blur effect. To make this visual effects similar to Apple's native visual effect, then we need to use the blood modifier here and there. That said, let's add a new block modifier to both the background image and the vertical stack container. First, we start with the V stack. Enter the following code. Block. Radius shown you task item, question mark, colon 0, a Paik, false. With this code, we generate a unique visual effect with this blood modify each time when the new task item view is visible on the screen. To make this transition more noticeable, we can attain you handy modifiers to this V-star. Enter transition. Move, edge. Bottom. Animation. He's out. Duration 0.5. Next, last but not least, we will add a similar blur effect to the background image. Navigate to the background image view and enter this code. Block. Radius. Shown you task item. Question mark eight, colon 0, a Paik, false. Final test. And guess what? We have just finished developing a custom visual effect. The only thing that we need to do is to build and run the project either in the simulator or on an actual device. Preferable The last one, because nothing can beat testing on a physical device and watch how this stunning visual effect works in reality. Wow, what an amazing effect it is. Now let's change the appearance too dark, shall we? Let's try it out again. Fantastic. Can you notice the difference between the light and dark visual effects? How cool is that? And do you know what the cherry on the cake will be? The next lesson where we will improve the user experience with multiple sound effects and haptics. Until then, happy coding. 10. Dealing with UX and Sound Design: In this class, we will improve the user experience and the overall vibe of this today's application. What I mean by saying that we're going to add different sound effects and haptic feedback to this swift UI app. Let's see how it sounds when we tack on the new task item button. It's an excellent chime, isn't it? Now, let's enter a new task item and listen to the next sound effect. It's the same time because I wanted the Add button and the save button sound to be identical. However, if you decide to change the apps appearance from light to dark, then listen to this new sound. Can you hear the difference next? Now let's check out some task items from the today's list. Shall we see? There it goes. That's what I'm talking about. We hear a sound effect that gives us positive feedback when we accomplish a task item from the list. Now let's listen to the sound effect. When we uncheck a list item. It's different. Now, Let's try it out again. Perfect. By the end of this tutorial, our devote application will get more value by adding different kinds of sound effects and haptic feedback. That's being said, let's launch Xcode and start coding along with me. First of all, we will create a new utility file for the sound player and reuse it as many times as we wish later on. Select the utility group from the project navigator, and let's create a new swift file. Give it the name sound player, and save it into this folder. In order to create a sound player, we have to import the audio video foundation framework. So let's do it. Enter import AV foundation. Now we can create a new audio player. Enter var audio player type of AV audio player. Question mark. After that, we will create a new function to run each time when we want to play a sound effect. Function. Play sound, sound, string, type, string. Great. Now we need to create a new path property and to the following code. If let path equals bundle dot main dot path. For resource sound of type, type. With this code, we can add the necessary sound file to the audio player that we want to play. The D that safely in the Swift programming language, we need to use proper do, try, catch, error handling. Enter this code. Do audio player equals. Try AV audio player. Contents of URL, file URL with path, path. Audioplayer, question mark, play, catch, print. Could not find and play the sound file. This is one of the best methods to play any selected sound file from the local app bundle. And we will use it all over the place in this lesson. Playing sound files. To play a sound file fast, we need to open the content view file. After that, please scroll down to the appearance button and let's run our new function. Enter. Play sound, sound, sound, tab, type, mp3. Okay, the first sound effect is done. Now, we will speed up this process and more sound effects here and there in this project, please navigate to the new task button section and let's add a new action to it. Enter play sound, sound, sound, Ding, type, MP3. Great. We're done here. After this, let's open the new task item file and scroll down to the save button. Here, Let's add a new action to this button. Play sound, sound, sound, Ding, type, MP3. Fantastic. Now we're going to play a different sound effect when users try to save an empty task, a warning sound will be a perfect candidate to give them feedback about this failed action. That said, let's add a new modifier to this button. On top gesture. If is button disable. Play sound, sound, sound, tab, type, MP3. Nicely done. We can now jump to the next file, open the checkbook style file, and let's run the sound player conditionally in the untapped gesture. If configuration is on. Play sound, sound, sound rise, type MP3. Else. Play sound, sound, sound tab type, mp3. With this code, we can play different sound effects depending on the status of this checkbox. Testing. After all this work. It's time to test how this nice sound player works in action. Let's build and start the application. First. Let's tap on the new task button as I do, super. Now enter a new task item and save it. It's working to what's about switching from light to dark mode. Splendid. And finally, let's see how we can play a sound effect conditionally using the checkbox. It works seamlessly without any problem. How cool is that? Haptic feedback? After successfully developing this sound play a using the AV foundation framework, we can finally create the next feature. This time we're going to add some haptic feedback for the application similar to the sound player. So do that. First, we need to open the constant file. Here in the user experience section, we will create a new property. Enter the following code. Let feedback equals UI notification feedback generator. Since this feedback generator comes with a handy method, that's why we can generate different kinds of feedbacks on iPhone devices to make it happen. First, jumped to the content view file, and let's add a new action to the appearance button. Enter. Feedback. Notification occurred six S. By running this simple method, we can create either success, warning or error types of feedback as we wish. Now let's continue adding this feedback three more times. First, scroll down to the new task button and add a new action to it. Enter. Feedback. Notification occurred six S. All right, We are done here. Second, we will add new feedback to the Save button as well. Enter. Feedback. Notification occurred success. And finally jumped to the checkbook style. And let's add the last feedback to the custom toggle element inside the untapped gesture modifier. As I show you, enter, feedback. Notification occurred. Six S. Awesome job. We have just finished adding two new features to this application. Again. Congratulations. Haptics setting. Just one more thing. The only proper way to test how this haptic feedback generator feature works is to try it out on a physical device. Please make sure that the system haptics is enabled in the iPhone settings to check it out. First, launch the settings app on your phone. Then open the sound and haptics settings page. As I show you here, scroll down to the end of the page and make sure the system haptics feature is enabled. With that, you're all set to test this new feature on your phone. All right, I hope that you enjoyed this short lesson and you are eager to watch the final tutorial. In the last lesson, I will introduce you to the new widget API. Are you ready for more awesomeness? I hope so. Having said that, see you at the class. 11. Introduction to the new Widget API: In the final lecture of this section, we will get familiar with Apple's widget kit framework. Using this widget Kit Framework and API, we can easily build widgets in Swift UI and make them available across iOS, iPadOS, MacOS. As you may know, widgets come in multiple sizes and users can visit the new widget gallery to search, preview sizes and place them anywhere on the home screen to access important details at a glance. Adding a widget to our app requires minimal setup and a few decisions about the user interfaces, configuration, and style. What you also should know about widgets, that they display their content using Swift UI views. In this tutorial, we will focus on how to create a static widget extension in Swift UI. Alright, without further ado, let's launch Xcode and start coding along with me. Widget extension. First of all, we start by learning how to add a new widget target to our existing application. To do that, let's open the devote project in Xcode and choose file new target from the main toolbar, many, we need to search for the widget extension using the iOS application extensions search field, as I show you. Now, please select Widget extension and then click Next. Then we need to enter the name of our extension. Give it the following name. Devote widget. Since our static widget won't provide user configurable properties, therefore, uncheck the include configuration intent, checkbox as I do. Excellent job so far. After all these settings, click finish. Shortly after we created a new widget extension, a new pop-up window asks us whether we want to activate the new scheme. Of course, we will click Activate and we're good to go. Widget template. The widget extension template provides a starting point for creating our widget. You can find this widget in a separate group folder in the project navigator. Please select the devote widget folder and unfolded to see all files in it. As you can see, there is an info property list file, then an asset's catalog, and a swift file. Let's select the devote widget, a swift file, and look at the default template structure. There is a bunch of code in this file, but don't be scared. We will discuss all of them. But before that, I will show you how we can build and run a widget extension in Xcode. Testing widgets. Go to the top toolbar and click on the scheme as I show you. As you can notice, we now have two schemes to targets. One for the devote application and a new one for this widget. And when we open this widget swift file, then this new scheme became the active target. That's why when we click the build and run, then Xcode starts compiling the widget for us so we can test it in the simulator or on an actual device depending on what we have chosen. As you can see, a new widget was added to the home screen automatically with the current time, it's worth mentioning that in a real scenario, no widgets will be added automatically when a user installs an application from the App Store, users can add a new widget to the home screen by editing it. One way to do that is to tap and hold our finger on any app icon or widget. This will trigger a new context menu. And after selecting the Edit home screen, we can see a new Plus button on the top left corner. Now let's tack on this Add button. As you can see, a new sheet showed up with a search field and the list of all available widgets. This is the new widget gallery. By default, all widget inherits an icon from its parent application. Please select the devote widget to choose a widget size or widget could potentially have three different sizes. To check them out, we need to swipe to the right and left. There are small, medium, and large size widgets provided by this template. All right, after learning how to build than one and test the widget template, we can jump back to Xcode and take a quick look what's going on under the hood. Basics. Since the new widget kit framework and it's swift UI API is a huge topic itself. Therefore, it's impossible to teach everything about it in this short lecture. That's why we need to take baby steps to get familiar with it. My main goal with this class is to build together a static widget. However, before doing that, it's worth knowing the basics of how a widget works. Having said that, let's get started. So what widgets, or in a nutshell, with widgets, users get timely information from their favorite apps at a glance. Also, uses, can use widgets on home screen to keep some content or helpful information at their fingertips. But not only that, users can use widgets from today view by swiping right from the home screen or lock screen. As for widget developers, we need to get familiar with three fundamental building blocks and how they work. These are the widget families, entries and timelines. Widget family. When we say widget family, then we think about different widget sizes, such as small widgets, medium widgets, and large widgets. The second important thing, timeline. The second important thing is the timeline. The way widgets provide information is through something called a timeline object. To tell widget kit when to update a widgets view, a timeline provider generates a timeline. A timeline contains an array of timeline entry objects and to refresh policy. With this, each timeline can manage how to update a particular widget, which is the actual data coming from the main application that the widget can use. Entry. And entry creates a timeline for when we want widget kit to update a widgets view. To create timeline entries, we need to declare a custom type that conforms to timeline entry. Each entry specifies the date we would like widget kit to update the widgets view and any additional information that our widget needs to render the view. Reload policy. The timelines refresh policy specifies the earliest date for Widget get to request a new timeline from the provider. What worth knowing about the reload policy is there are three types. The default refresh policy at end tells widget kit. And request a new timeline after the last date in the array of timeline entries we provide. This means when the end of the timeline is reached, then the widget will start over with a new series of entries. It will keep updating the widget for undefined times. The second type is the so-called after date. We should use them after date it to indicate a different date, either an earlier or later than the default date. Specify an earlier date. If you know there's a point in time before the end of your timeline entries that may alter the timeline. Conversely, specify a later date. If you know that after the last date, your timeline won't change for awhile. And finally, never is the third reload policy type. Alternatively, we can use that never policy to tell widget kit not to request a new timeline at all. In that case, our app has to use widget center to prompt widget kit to request a new timeline. When we decide to use this policy, our responsibility is to determine when updates will be executed. Limitations. Just keep in mind that widgets are not many apps and they have limited capabilities. And this is designed on purpose, so Widgets couldn't overuse or abuse the devices, energy, memory, and other crucial resources. Also, note that the widgets view might not be updated precisely at a timeline entries, data and time. That's why the update mitochondria later. Widget template. Now that we can understand the basics of widgets, then we can jump back to Xcode and walk through all kind of the default widget files. First things first, as you can see, we have to import the widget Kit Framework. It's as simple as that. Second, we have a provider's drop that conforms to the timeline provider. A timeline provider advises widget kid when to update a widgets display. There are three required functions in the protocol. Inside this timeline provider, a widget placeholder function provides a timeline entry representing a place holder version of the widget. After that, there is a guest snapshot function that provides a timeline entry that represents the current time and state of a widget. And finally, there is a get timeline function that provides an array of timeline entries for the current time and optionally any future times to update a widget. Pay attention to the code inside this function. First, there is a current date property. The second part generates a timeline consisting of five entries in our part starting from the current date. Particularly a useful widget in my opinion. But hey, that is what we got so that we can use it as a starter point. Next, there is a simple entry struct with only one property a date, so that widget kit can render a widget with it. The next section here is something essential to know. As you know by now, we can only create a widget with Swift UI. Since widget kid is a brand new framework, Apple decided to leave behind the old technologies, aka UIKit, in favor of Swift UI. This devote widget entry view is where we create the actual layout and design for the widget. As you can notice. There is a body part similar to our main app. So far, there is nothing fancy there, only a text view. But at the end of this lecture, this code will be dramatically changed. Next section, don't be confused about the order of these sections. It will be pretty logical at the end, this block is the most crucial part of widget creation. As you can see, we develop a widget by creating a struck that conforms to the widget protocol with the at Main attribute, we declared that this struct will be the entry point of this widget. So the app will take care of creating all the needed things to start this widget when the time comes. The only requirement of the widget protocol is to provide a body property that should return an instance of widget configuration. Swift UI provides us two structures that can form two widget configuration, a static configuration and an intent configuration. We can use intent configuration to provide user configurable options for our widget. A great example of that is Apple's weather widget in where we can select the current weather conditions and forecast for a location. In this lecture, we're using static configuration. The static widget configuration allows us to register a widget configured by the developer that from time to time updates its data. Also, the static configuration needs three parameters. Let's take a look at them. One by one. Kind is a string that identifies the type of widget. You might have multiple widgets. The provider conforms to the timeline provider protocol and is used by the system to fetch widget data. Finally, we need a view build a closure that describes the swift UIView for displaying widget data. With all these settings, the system will try to predict the best time to perform widget updates using providers. But we can always ask to update widgets using widgets center. We will learn how to develop more advanced widgets later on in this masterclass. Now let's move on to the last code blocks in this file and start doing something worthwhile. Widget previous. Please scroll down to the previous section. As I mentioned before, widgets usually come in three different sizes, small, medium, and large. In my opinion, it's worth knowing how we can test these different widgets properly on the canvas. First of all, select the whole, uh, devote widget entry view with its modifier as I show you after that Command Plus click on this views name from the context many, please select the embed into a new group option. As I show you. Great insight, this new group, we need to paste the code snippet two more times. So at the end, we will have three widgets altogether. Last but not least, let's modify the widget family for the second, third widgets, shall we enter family system medium? Then enter family system large? And there it goes. With this modification in the previous section. We can visually test all widgets from the smallest to the largest ones. How cool is that? Widget assets? Regular iOS projects share many similarities with widgets. For example, both of them have a dedicated asset catalog. Please select the assets group in the project navigator. As I do. As you can see, a widget could have its own accent color, app icon. And what's new here, a dedicated widget background. We will continue by adding icons for this widget. First, select the app icon in the middle pane. Now Control Plus click on its name. This will pop up a new context. Many She's dead Show in Finder option from this many. After that, open the app icon folder. There are no icons. Now we need to open a new Finder tab or window. As I show you. After that, please navigate to the Resources folder. In this folder, we can find a widget folder as well. I open this folder, there is a widget icon inside it. Now open the app icon group and select All files inside this folder and copy them to the clipboard as I do. Finally, switched to the empty app icon folder in the previous Finder tab and paste all files from the clipboard into this group. As you can notice, shortly after this, our new widget got dedicated icons that could be different from the inherited iOS apps icons if we wish to differentiate them for some reason. Next, go back to the widgets resources folder and select the rocket image. After that, drag and drop it into the asset catalog as I show you super, to sum up what we did so far, we added a graphic file and dedicated icons for the widget. Now let's do something new. Please select a widget background asset from the middle pane. As you can see, this is a special color set with no default value. Now select this empty colors slot in the editor. As I show you. After that, we make sure that the inspectors pain is open. So let's do it. Activate the attributes inspector, which is the fourth many. In this attribute inspector, we can add any new color that will be used in the widget editor. More specifically, it will be the background color of the Add Widget button. Click the contents. None option. She's the sRGB color spec from the drop-down menu. As I do here, we need to change the input method from floating point 2, 8 bit hexadecimal. After that, enter the following color Valley. Hash, D 13885. This valley will generate a nice pink color for the buttons background. Shared assets. So far, we practiced how to add dedicated assets for a widget. However, there is another way to do it by sharing an existing asset of the main iOS application. And this is what we're going to do right now. First open the assets catalog in the devote iOS app group. Now please select the logo file from the middle pane as I show you. After that, go to the inspectors pane on the right hand, and select the file inspector from the menu bar. As I do in this file inspector, we can see a new target membership section. As you can see, this logo file is active only for the highest application. It means that only the iOS app can use it and nothing else. Our goal is to make this logo file available for use File widget as well. To make it happen, we need to check the checkbox option and modify the target settings. It couldn't be easier. I'm I right? From now, we can use this logo file in our widget target. I hope that you learned something new by doing this exercise, widget creation. In the rest of this lecture, we will create a static widget that will adapt to all sizes across the board. But before doing that, I would like to highlight two settings that we can further modify. We can notice two new modifiers in the main devote widget, namely the configuration, display name, and the description. Let's change the default values a little bit. Shall we, for the name, enter this text. Devote launcher. And for the description, this one. This is an example widget for the personal task manager. You will see how this information will be shown in the widget editor later on. Next, first of all, navigate the cursor to the body section of that, the devote widget entry view. Then comment out the TextView with the time. We will replace it with our custom design and content. Nice. Now let's start developing the new design. And to the following code. Z stack. New comment, the end of the z stack. And enter this code. Background gradient ups. Something went wrong. We got a new error message that the compiler couldn't find the background gradient in our widget target. This happens when we forget to share a specific file with the new target. To fix this, first, we need to open the constant swift file. Then in the file inspector pane, we have to add the widget as a new member of the target membership. So let's do it right now. It's done. We can jump back to the devote widget and continue our work. See the error message has gone and there is a new linear background in each widget on the Canvas. Next, on top of this background, we're going to put two images and a text view. Let's start with the rocket image. Shall we enter the following code? Image? Rocket dash, small. Resizable scale to fit. As you can notice in the preview, the image has been scaled up or down depending on the particular widget size. We can continue by adding the logo to the top right corner. Enter image. Logo, resizable, frame, width, that is X, height, that is x. Now we need to move this logo to the top right corner. And one of the possible solutions to do that is using Swift GUIs geometry reader. First Command Plus click on the z stack, then select the embed option from the context menu. As I do. After that, we need to replace the placeholder container with the geometry reader. Geometry reader. Geometry. In new comment. The end of the geometry reader. So far so good. With the geometry reader, we can precisely positioned the logo image wherever we want. To do that, let's add the following modifiers to the logo. Enter. Offset. X, geometry dot size dot width divided by two minus 20. Why? Geometry dot size dot height divided by minus 2 plus 20. This code will position the logo to the top right corner of the widget. Now let's add some padding to it as well. Enter padding. Top 12, padding, trailing 12. It's much better now, next, let's create a new text view after the logo. And to the following code. Text. Just do it. Foreground color, white. Font. System. Footnote, design, rounded. Font, weight, bold. Padding, horizontal. 12. Padding, vertical. For background. Color. Red, green, blue, 0.50. Blend mode, overlay, clip shape. Capsule. We're almost done. Now, please embed this text view into a new horizontal stack container. As I show you, each stack. New comment, the end of the horizontal stack. Nice. For now, it does nothing but later on, we will use it for father positioning. After all this, we need to add some new modifiers to this H stack. Enter padding. Then offset y. Geometry dot size, dot height divided by two minus 24. This offset will ensure that the TextView is always positioned at the bottom part of the widget. We could call it a day because the general design of our widget is completed. The layout and the local identical in each widget, as you can see in the preview. However, we can make it much better if we could differentiate them from each other somehow. That's why I would like to show you how to make the design adaptive depending on the widget family. It sounds great, isn't it? So without further ado, let's do it. Widget family. First, we're going to create a special property that we can use in different conditions. Navigate to the top of the widget entry view and enter that environment. Backslash dot widget family, variable, widget family. As you can see with this environment property wrapper and the widget family key, we can get the actual size of any widget instance. Also, we can always use this widget family environment Valley to understand the current widget configuration size and present different views. To prove it for you, scroll down to the stack and let's create a new conditional view off to the text. Enter this code. If widget family not equal to small, then add a new spacer to it. And there it goes. Dc. How we move the text to the bottom left corner with this code in the medium and large widgets. How great is that? But we do much more using the widget family property, jumped to the logo view and let's modify the frame modifier as I show you frame. Then let's wrap the width and height attributes in new lines. Width, widget family, not equal to system. Small. Question mark. X colon fat is x height. Widget family not equal to system small. Question mark 56, colon, fat is x. Now we need to adjust the padding of the logo a little bit. First, select the code from the widget family to the question mark and copy it to the clipboard. With that, now, we can modify the padding. Second, paste the code from the clipboard before the value. As I do that, enter theta2, colon 12. And last but not least, do the same with the trailing as well. Paste the code from the clipboard, then enter fatty to Colin 12. As you can see, we can make any UI elements bigger or smaller depending on the widget family. Font varieties. We went stop here and I will show you another way how we can use this widget family. Alright, scroll up a little bit so we can create a brand new computed property. Enter the following code. Variable, font-style, font type. If widget family equals to system small, then return system. Footnote. Design, rounded. Else, return system, headline. Design, rounded. With this code, we can differentiate the size of the text to see how we can do it. Navigate to the text view and modify it. Font, font style. There it goes. Can you notice the subtle differences in the previous I hype? So this widget family environment property gives us the power to change and modify the layout and design of each widget conditionally as we wish. How cool is that? I hope that you can appreciate its benefit as much as I do final test. And that's all for today. We have nothing to do here. Let's build and run the completed devote application, either on an actual device or in the Xcode simulator. So let's do it. We start by editing the home screen as I show you. Then we need to select the devote widget from the widget gallery in the widget editor. Now we can select any static widget that we want to add to the home screen. By the way, do you see the custom widget name with its description? Not to forget about the pink button at the bottom. Our new widget extension conforms to the overall design system of this application. How amazing is that? All right, after we choose a widget, then we enter an edit mode where we can move the widget to their preferred location. I'm quite speechless that you came along with me so far. Please take my congratulations. You did a great job developing this fantastic mobile application. And I really mean that what I would ask you is to stand up, leave your computer and show your friends and family members this awesome app as soon as possible. But not only that, you can share your achievements on social media as well, undoubtedly, you deserve recognition from others and let the world see what you have just developed. You got the momentum. So don't stop now. I hope you will enjoy the upcoming sections, cool projects as he did so far in this masterclass. Just one more thing. I would appreciate it so much if you could take the time to give this course of five-star rating. Or even better if you could share your learning experience with other students by writing a helpful review about this course. This way, you not only motivate me to publish more practical projects to this masterclass, but at the same time, you can help other students to be informed about this excellent learning material as well. Either way, I would be glad to read your success story too. Thank you so much.