UIKit - SwiftUI Integration

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi my name is stuart nich and in this video i'm going to show you how you can incorporate swift ui views into your ui kit apps now that ios 15 has been released most developers are comfortable supporting ios versions that are current minus 2 which means ios 13 and this is the first version that supports swift ui so if you've brought into the swift ui like i have you'll appreciate how easy it is to build your views what i'm going to show you today is how you can update an app with an original target of ios 12 and update it to a target of ios 13 and replace a ui slider on one of the view controllers to instead use a custom view designed in swift ui now this will require the use of a hosting view controller before i get started i want to ask that if you enjoy this video please give it a thumbs up and subscribe to my channel make sure you ring the bell to be notified of future videos comments and likes are always appreciated and if you care to support my work you can buy me a coffee if this is something you want to learn then keep watching i've created two starter projects for this video the first is a sample app called my books and it uses ui kit it's a simple app that lists a number of books that i've read and when you tap on the book you can edit the name and author select the genre and change the rating the updates are reflected back in the list view and in particular note the rating which is this star icon with the rating number inside you can also add new books and delete them i have not however added any persistency to this app it's for demo purposes only so none of your changes will be saved what i want to do though is to be able to replace this awful ratings ui slider control and that brings me to the second starter project which is a swift ui view and when you tap on a star the image is changed so that all of the stars are filled up to and including the tapped one tapping on a red x will clear the rating what i want to do in this video is to take this swift ui view and replace my slider then here in uikit app when i tap on a star to update the rating and update my book that change is again reflected back in the list view too before i show you how to do this though let's first take a look at the starter project code the view controller is a typical ui kit app with a table view listing all of the books there are actions to add a book and to delete one in edit view controller you have all of the outlets that correspond to the properties in a single book which we have here in our model the genre is an enum with some computed properties that will allow me to present the raw value capitalized along with a corresponding emoji there are also two static functions that will give me the array of emoji items to use for the genre picker and one that will be able to determine the index for a selected item in the array there's also a static array called sample books that gets loaded when the app launches back in the edit view controller then the things that we'll need to pay attention to and change are the rating slider ib outlet the slide changed ib action and the update book functions so that when we replace the slider we'll still be able to update the ratings on our book the ratings starter app is a swift ui app that i built using xcode 13 but the app itself does not use any ios 15 features at all in fact the view is completely compatible with ios 13 the first iteration of swift ui the control is a slightly modified version of the one that i created to demonstrate how to create a swift ui package and i'll leave a link to this video in the description below the package however currently only supports swift ui and we want to use the new view in our ui kit app so it's going to require some modifications the view currently in this sample project is quite simple and we've seen how it works but it's not reusable even within this swift ui project the view is this entire v-stack so i'm going to extract it into its own view so let me close off this preview for the moment and i want to create a new swift ui view that we'll call readings view let me option click on content view so that i can see both of my views on the screen at the same time now our view is going to be this entire content view so i'm just going to copy the entire view and the preview and paste it in to replace my ratings view and then make sure i update wherever it says content view to readings view and we only need to do one more thing here when we use this view in swift ui we want to be able to respond to state changes so we'll need to change the current rating to a binding and remove the default value the remaining properties are all variables all with default values so when i create a ratings view in any one of my views all i really need to do is to pass in the binding unless i want to change the number of items the color the width or the sf symbol used for the ratings so back in content view we can keep the state variable but remove the remaining ones here and replace the v stack in the body with an instance of our ratings view passing in the current rating accepting the default values now let's go back to our content view and preview again and see that what we can do now i want to create a second ratings view but i want to use hearts and i want to have the reading go from 1 to 10 and be read to match the hearts so first let me embed my current ratings view in a v stack and i'm going to add a new one above it now when i start to create my readings view you'll see that i have two options for my initializer that second one is the one that's going to allow me to enter values for one or more of the remaining arguments but remember if you leave one out it'll just take on the default value so the first thing i'm going to need is a binding to a state property and it's going to be different from the one that we use for our stars so i'll need to create a new one that i'll call currentlove and i'll initialize it initially with a 0 as well and then we can use that for our binding i want to set the max rating to 10 the color to a ui color of red i'm going to leave the width at the default so i can remove that argument altogether but for the fill image name i want heart dot fill and for the open image it's just the sf symbol which is a heart if i refresh the canvas now i'll get both ratings on the content view and both of them are independent of each other so that i can set ratings on one or the other or both as i see fit well this is perfect i want to use one of these views inside my ui kit app to replace that ui slider so let's open our ui kit app now using this version of xcode and the first thing i want to do is to make sure that it requires ios 13 as a minimum so i'll need to go to the target and set the deployment target to a minimum of 13 and we do this both here on the target and on the project as well the next step is to add the swift ui view from our ratings app to this project and this is as simple as dragging from one project to the other now it's time to change our ui layout so we can use that new swift to eye view and we do this by way of a hosting view controller so let's go to our storyboard and start here first thing i'll do is click on the rating slider and the ratings label and delete them both next i'm going to add a container view i'll just drop it on and drag and align it to the location where i just replaced those two other controls i'll delete that view controller that was created for that container view and instead i'm going to add a hosting view controller to link up our container view to that hosting view controller i can control drag from the container view to the hosting controller and choose embed i'll select the segway and give it a unique identifier like to ratings view i need to fix the constraints now so i'll make sure that i center in the container view horizontally and then i'll add a standard vertical spacing and i'll fix the width and height to those dimensions where i drew it next i'll have both the edit view controller and the storyboard opened together i'm going to control drag the segway to the hosting controller from our storyboard onto the class to create an ib segway action function and i'll give it a name like to ratings view what gets returned is a ui hosting controller with two properties a coder and a root view for the coder it's just the coder that is passed in and for the root view we'll specify our swift ui view which is our ratings view and we'll just choose the default implementation for now we have a problem though what we want to pass in is not a binding but the value of our book rating if it exists or zero if it's new and we can't pass in a state object because there is no such thing as a state property because we're currently in ui kit so we'll need to go back to our ratings view and we'll change that binding just to a local state variable to keep this current rating local and initialize it as 0. and instead we'll create a new property to pass in from our view color drawer so we'll call it passed in rating and it'll be an int now we'll have to fix our preview by passing in a default value and then finally when our view appears we'll assign that passed in rating to our local state variable the current rating so that it can be updated from within this view back now in edit view controller we have to remove all references to those two controls that we deleted the rating slider and the rating and make sure we remove the ib action as well and for the update book function let me just comment out this offending line here and this here well we can now change the argument to our ratings view into a passed in reading and that'll be the facebook rating if it's not no otherwise zero let's run and see how we're doing so far if we tap on a row we get to our edit view and indeed we see that new ratings view displayed correctly with the correct number of stars filled and tapping on one will change the rating however when i tap on update the rating is not reflected back in our list view we still need to somehow convey back to the calling view that this rating has now there's a couple of ways to go about doing this we could use a protocol and delegate pattern but i prefer to use closures with a closure you can pass in a function from one view to another and then use the value from the second view as the argument for your function so if we had a function in our edit view controller that has an integer parameter that is used to update the value of our rating on this book we can pass that function into our swift ui view and have it use the updated rating as the functions argument so let's do that in edit view then we'll create a new function called update rating that has an int as a parameter and all it does is set the value of the rating for this book if it's an update or if it's a new value we're going to assign that rating to the new instances rating we'll call it update rating with one parameter that we'll call value and it's an end so if this book is not nil meaning we're doing an update we can unwrap it and set the rating to the value that we received if it's not nil we'll still need to hold on to that value until we decide that we want to create a new one so i need to create one more property in the edit view controller that's an in that we'll call new rating and we'll initialize it as 0. then in the update ratings else clause we can set this new rating to what we get as our new value and then finally we can remove this commented outline altogether here if this book is not nil and then we'll just uncomment out this new book section but we'll assign the new reading to the reading that we have here well we're almost there we'll need to pass this function into our swift ui view so let's return now to ratings view and i'm going to create a new property that's called update rating and it's a closure type that will have an int as an argument and return void and i'll create that right after our past in rating property i have a video on closures so this is confusing to you i suggest you watch that video and i'll leave a link in the notes below now in our tab gesture we can where we update our current reading pass that update to the update rating function and we'll need to do that each time that we update that current rating we'll also need to stop xcode from complaining by updating our preview so let's just create a static function called update reading that accepts a value as an int but does nothing and then we'll use this just as a placeholder so that we can use it as the argument for our preview now this of course breaks our call in the edit view controller so let's fix that since our argument type is looking for a function that has a single int parameter returning void we can pass in that function that we created earlier just as its name the update rating function so let's test this out if we run in the simulator let's tap on a book and when we update the rating we see that it gets updated in the list as well let's create a new book how about absolute rage and the author is robert tannenbaum it's a thriller and i'm going to give it a rating of 4 out of five when we exit our fields the create button is active we can create it and we can see if the object is created it's showing up in our list view with the correct rating so i hope you found this tutorial helpful and can see a practical use if you have old ui kit projects that you want to maintain yet move forward in swift ui thanks for watching [Music]
Info
Channel: Stewart Lynch
Views: 628
Rating: undefined out of 5
Keywords:
Id: 9urhPz9OGzQ
Channel Id: undefined
Length: 19min 34sec (1174 seconds)
Published: Sun Oct 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.