MVVM Swift 5: Model View ViewModel Design Pattern (Xcode 12, Swift 5, 2020) - iOS Development

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] what is going on you guys welcome back to another swift video in today's video as you can see we're going to be talking about the mvvm otherwise known as the model view view model design pattern in ios so this has been requested time and time again i've done a video on this quite a while ago so i figured i'd do a more updated one as well as a one that's you know put together a little better so we're going to talk about this we're going to take a look at implementing it with the basic example we'll also talk about why this is a thing and why it's better than mvc in a lot of folks opinions as well as mine so that all said make sure you destroy the like button as per usual helps out with video engagement and the youtube algorithm hit subscribe if you're a returning viewer get xcode ready get excited let's talk about some mvvm quick pause before we get into the video if you haven't seen it already i am hard at work putting together ios academy dot io a community where all of us ios engineers can come together learn how to build some of the top apps like facebook youtube and instagram in addition to interview prep to land some of these ios roles at top tech companies so if you're interested in the free and premium content to come head on over to iosacademy.io and enter your email address in the waitlist form and you will be notified as content becomes available that said let's get into the video alright so we're going to get started by opening up xcode and creating a new project here we'll stick with the app template and i'm going to go ahead and call this mvvm example make sure your language is swift interface is storyboard and lifecycle is uikit go ahead and continue and we'll save it to our desktop and we're going to start off with the view controller file but before we get there once xcode decides to stop being slow like that we're going to pick a simulator from our list up here we'll stick with the 11 pro max go ahead and hit the run button let me expand this window a little bit to give ourselves a little more room to work and the example we're going to be doing uh today is with a table view and custom table view cells and the reason i think i went with that is it's a really common example and use case that's used both professionally and most probably in a lot of your guys apps as well so that said let's pop into our view controller here and i'm going to bump up the font size so we all can see it and let's get into it so first things first we want to create a table view on here and we're going to set it up in the mvc architecture so model view controller so we've got our controller bit here we're going to create a model right above it and then we're going to create a custom table view cell which will be our view so we're going to start off with that and then we're going to expand it to be mvvm which is model view view model so there's a new thing there which is view model we're still going to retain the controller so cool so let's create a simple table view on here so we're going to create a table view as follows just like this with an anonymous closure and there'll be a ui table view go ahead and return the table just like that we need to register a cell to it so we're going to say uitableviewcell.self and the id that's going to be used is cell we're simply going to add it as a subview here and we're going to assign its data source we're going to also want to give it a frame of view.bounds which is the entirety of this view controller we'll get an error here in a quick second like that because we're not conforming to the protocol up here so you want to go ahead and add conformance to the ui table view data source and then there are two functions that are required that we'll need to bring in the first one is number of rows let's just hard code that to 10. we'll get that from our models in just a moment and the next thing is sell for row at index path and here we're going to dequeue a cell with the identifier of cell for the given index path we'll say cell text label dot text dot text oh no autocomplete really likes to not cooperate half the time it's on text and we'll assign this to be hello world and finally go ahead and return your cell so the error should go away i know we didn't create the model yet we will in a second just hit run to make sure that we've got our table view showing up what i'm also going to do is let's pop into the main storyboard and let me embed this inside of a navigation controller so hit the controller here come up to editor and we want to go to embed in if i can find it embed in and we want to hit navigation controller and let's uh let's give this a title so select the title uh bar up here the navigation bar and we'll just go ahead and call this home command r again and you should have a navigation bar at the top of your controller cool okay so we've got our controller bit down our view in this case is the table view as well as this reuse table view cell uh but we want to add a model to this right so we're gonna create a struct and this is going to be let's call this an option and we're going to say this has a title on it which is basically just a string let's actually call this a person let's make it let's make it a little more realistic and we'll give a property on here called name and we're going to have a private var on here called models which will be an array of uh person objects and right here in view did load we're going to say configure models which will be a separate function and you guessed it in this function we're going to set up our models and put them into that array we created now number of rows is going to be models.count and here we can say the um the text is going to be the text in the model so it will say models or mod dolls or model singular is from the models array at the given position and here we can say model dot name just like that and then in here let me go ahead and create a array of names really fast so we're going to say joe dan jeff let's see jenny and emily and what i'll simply do here is in a simple for loop i'm going to say for name and names we're going to say models.append a person with a name and we'll just pass in the name there that way we can get all these created and if we go ahead and hit command r now we should now see our names in here with the appropriate number of cells beautiful so cool so we've got our controller down our model now we want to separate the view as well as introduce a view model so maybe i should have led off with this but what the heck is a view model so the purpose of mvvm is really to separate out uh individual concerns or responsibilities even more so with model from model view controller so a model of course is your data layer you've got models that represent your data wherever it's coming from either the network or a database what have you you have a controller that's responsible for you know tying the model and the view together and then you have a view in which you present that data in a gui right your user interface so it's a view model so view model is basically an intermediate between the model and the view so what happens oftentimes in larger applications is models get really large sometimes so for example we're going to stick with this person and let's think about the facebook app right so in facebook's ecosystem a person and i'm going to go ahead and create these with um optional values a person has a ton of different properties on them so a person could have let's just call a birth date actually they can have a birth date they can have a middle name they can have what else they can have a address they can have i'll just add one more for the sake of brevity uh they could have let's say a gender which is of a type gender and we'll just create a gender enum here of case male female or unspecified specified and the point is sometimes in a view you don't necessarily want to show all this data at once right so what you want to do is create another trimmer object that only has the model information that the view really cares about and when the view model updates we want to be able to update the view accordingly right so how do we do that quite frankly it's fairly simple so we're going to create a struct actually before we even do that let's take let's take our cell and separate it out and create a custom cell let me also separate out these models so i'm going to create a new file here right click new file and we're going to stick with the swift file and i'm going to go ahead and call this models we'll just paste in our models in there just like that fairly straightforward and let me drag this file up so they're nice and organized and let me create another new file and this one's going to be a coco touch subclass and it's going to be a custom subclass of a ui table view cell and i'm going to go ahead and call this person following table view cell and that name will make sense in just a moment and let's go ahead and implement our table view cell here so first things first we want to give it an identifier like that and we're going to override the initializer here which is in it with style uh oops not that one we want in it with style we're going to say super in it with a style and a reuse identifier we're also going to want to bring in the other required initializer with the ns coder here we're going to also want to add layout sub views and override it we're also going to want prepare for reuse prepare for reuse and call super prepare for reuse this error should go away it's just xcode being dumb perfect okay now what we can do is go back to our view controller and let's actually use our new cell here so here instead of registering a normal table view cell we can go ahead and do let's see this error should go away hopefully cannot find person and scope let's go ahead and hit command b it should go away all right cool looks like we saw an error somewhere we'll take a look at it in a second but let's register this cell for the cell names on identifier and then wherever we dequeue it down here i see what the problem is here we need to change the initializer but wherever we dequeue it down here in the cell for row function what we want to go ahead and do here is dequeue our cell with the new identifier so we're going to say the cell name dot identifier so what we've gone ahead and done now is we've separated out our our view layer so if we hop into our models file here let me create a initializer which only requires the name and the reason i'm going to do this is because that constructor that we're using there in the view controller is going to continue to complain if we don't specify all the values so i'm just going to go ahead and assign all of these to be nil looks like we've got one two three and four so let's see what we've got going on we've got middle name middle name address is an address these are both strings and this last one is uh gender of type gender we'll default it to unspecified and get rid of that last comma and then in here we can just say self actually i could be lazy and copy and paste all this and let's get rid of that bear with me while i get rid of all this stuff all right so we're here we're going to say self.name is name all right that looks good we need to add one more curly here that looks good as well let's get rid of this and this and this and finally that and we should be good hopefully we want to change this to be the appropriate property for each of these bear with me all right cool so here we have our model we should be able to compile now everything should be working looks like we have three errors still so let's take care of these let's see what the issue is here so here we're saying super in it this one should be reused identifier looks like i messed up the autocomplete i'm sure some of you guys are pulling your hair out as you saw me typing that but now if we hit command b no errors go ahead and run you should see nothing different on your table view here but we're going to make it different in a quick second so cool so we've talked about the controller here we've separated out the view in our table view cell we've got our model set up let's introduce a view model so i'm going to create a new file here it's going to be a swift file and generally the way i like to name model files is it's going to be the cell rather than the view that we're going to configure so i'm going to call it person following table view cell view model so person following table of view cell view models kind of a long name but this way it makes it fairly clear in your project what view the view model is backing let's put them side by side just like that and in here i'm simply going to create a struct which is going to have the same name so what is this cell going to show us so you might have guessed it by the name of it but we're going to create a cell which is pretty commonly seen in apps like facebook and instagram where there's a person's uh image here their username maybe their uh rather their name their username underneath it and then a follow button or unfollow button based on the current state so let's go ahead and set up this custom cell so we're going to want to create four things on here the first one is going to be a user image view and this is going to be an image view and i'm going to try to go through this fairly quickly because this video isn't really about custom cells but bear with me if you're not familiar with custom cells i encourage you to watch my earlier video on it because it's helpful to get some context about uh kind of why we're setting up the custom cell but we're going to say aspect fit and then we're going to want two labels on here so we're going to say the first one is going to be user name label and this one i'm going to leave pretty basic it'll just be a ui label return label and let me just give this a text color of secondary label just like that i'm going to be lazy and copy and paste this right above it and this one is just going to be name label text color of label and then finally we want the actual button to follow or unfollow so i'm going to say private sled button is a ui button and this one is going to be a very standard ui button uh and that's actually all we want to do because based on the view model we're going to configure if it's a follow button or an unfollow button fairly straightforward so let's go ahead and add all of these sub views so here we can say content view add sub view and we want to add all of these sub views we created so there's four of them so our two labels our button and our image view uh we are also going to say content view clips to bounds is true and we want to give all of these uh sub views a frame so first let's do the image view so we'll say the user imageview.frame is cgrect with the x of 5 5 content view frame.size.height minus 10. and same thing for the height i'm just doing these calculations pretty quickly at the top of my head so bear with me the name label is going to be again cg rect the x is going to be let me actually make this uh image with right here we'll say image with is that and then this is also going to be image width here and here we're going to say x is image width plus 10 y will be zero the width here will be content view dot width minus weather.frame.size.with minus the imagewave and the height is going to be contentview.frame dot size height over 2 so that's that label copy and paste it once let me align all these properly then we want the username label right below it so we're going to say the username label is going to be the exact same but the y here is going to be halfway down so content view frame size height over 2 just like that and then finally we want the button itself so the button is going to be c to direct with the x y width and height the x is going to be content view frame size width minus 120 v y will go ahead and say uh is uh 10 the width is going to be 1 10 and the height here we'll say is content view frame size height minus 20. so i know we just did a bunch of math there hopefully that's all correct and hopefully you guys can uh just go ahead and copy copy all this stuff out let's go ahead and run this now and let's see what we get we're actually not going to see anything different on the screen what we will make sure is that things are compiling so now what we want to do is let's go set up our view model a little bit more so we created this viewmodel file right here and in here if you think about it what do we need to actually render out our cell well the first thing we need is a name then we want a username then we want a current currently following right which is going to be a boolean so this will basically specify if the user that's viewing this list is currently following that user and then finally we're going to want a let's see we're going to also want a image we'll just call it an image for the sake of simplicity it might be an image url in a real view model but since we're not using any backend service we'll just go ahead and whoops let's get rid of this we'll just go ahead and call it a ui image for now and this is basically everything that we need to render out our cell so how do we actually use this we can now go to our cell and in here we're going to have a function and this function is going to be configure with model and quite simply in here we can say name label dot text is view model dot name and let me go ahead and start copy and pasting this three times next one we're going to say is the username label text the user image view dot image and here we can say user name here we can say image and then finally what we can do is we can say if view model currently following we want to show an unfollow button otherwise we want to show a follow button so we can say in this case button set title unfollow for state normal and we can also say button set title color it's going to be black for state of normal and let's see what else do we want to do we probably want to give the button a border so we can actually see the edges of it so we'll say button dot layer dot border width is one button dot layer dot border color is ui color black dot cg color and i'm going to go ahead and copy this stuff to the other state so if currently following is false we want to show a follow button so we'll say follow and this one actually was supposed to be black not blue and in this case the title color will be white so you can see here is based on the view model we're configuring the view stuff so we don't the view has no knowledge of the actual backing model here from which the data is coming presumably some some model that's coming from our uh from our like api call or something like that so we'll say in that case uh background color is link which is just a flat blue colors go ahead and hit command v to make sure everything is still compiling and now what we want to do is in our view controller to actually use this model we're going to first want to say guard the cell and we want to try to cast it to the appropriate cell type and if we're not able to cast it as such we're just going to return a basic table view cell and now here we can use that configure function right we can configure with the view model but we want to create a view model from our model so we're going to say person follow view cell and here if we try to rather view model if we try to create this we have to create it with all this info but we want to actually create it with our model so i'm going to say with and pass in the model there now the next thing you can clearly tell is we need a way to use a person to create one of these view models so i'm going to come here and i'm going to create a constructor on this with model of type person and just for the sake of this video in an example we're going to say that the name is model dot name the whoops spell this correctly we're going to say user name is model dot username and i'm aware that we don't have a username on here yet so let's go ahead and just add a default one so we're gonna say var username is i don't know kanye west and realistically it would be configurable in the initializer but for the sake of not being redundant i'm just going to add it here directly like that and go ahead and hit command b and that should be compiling and let's see we still need to add the other two here so we're going to say currently following is going to be false and here we'll go ahead and say the image is a ui image and i'm going to use a system image of type person so cool so go ahead and hit command b now let's see if we have any errors so no errors let's go back to our view controller and the really important takeaway here is that the view model is created via the model and let's say we made any change on our view so for example the user taps a button and it follows the user we want to propagate that information back to the model and the reason is because the next time we render the model we want to show the appropriate view so a follow button versus unfollow and the view model needs to know what it needs to render given the current state so before we get into any of that let's go ahead and hit command r and you'll start seeing here now that we see follow buttons we see the person uh we see the name and looks like we don't see a username so let's see what gives on our cell why we don't see the username so let's go back to our cell and let's double check this stuff so let's see looks like we're adding the username uh we're adding the username interview twice where we wanted to add the username label username label that's what we want let's go ahead and try that one more time cool so now we have our name our username the image view as well as the button so right now tapping the button nothing happens right so how do we get this information uh back to our model to create our viewmodel correctly the next time we're going to use a delegate to do that but before we do that it's prepared for reuse function every time a cell is reused we want to reset all these properties so i'm going to say name label.text is going to be nil username label.txt is going to be no user imageview user imageview.image is going to be nil and we also want to reset that button so we're going to say button its background color is going to be nil and i'm also going to say button dot layer dot border width or we just say border width is going to be 0 and then we also want to change its title so we're going to say set title will be nil for control state of normal so this will reset our button every time now we want something to happen when the button is tapped so we can basically uh bind the action to our model so we're going to introduce a delegate here so we're going to say protocol person following table view cell delegate of type any object so it can be weak and here we're going to say func person following table view cell we're going to pass in a reference of it of the same type just like that we're going to say did tap element or did tap with view model and you guessed it the type here is going to be the same type here plus view model just like that and on the cell we're going to introduce a weak property for the delegate and this is how we're going to convey the data back to our controller now notice that we pass in the view model into our actual function here so whenever we call this configure function one thing we want to do is we want to go ahead and save or rather retain the view model onto the cell so i'm going to create a private var of viewmodel here and the type of it is going to be the view model type and it'll be optional and the reason we want to do this is because we're going to now add a action to our button just like this so we're going to say the selector is did tap button and we don't want the view to necessarily know what we're doing on the tap in this case we'd be changing the state of following so we're going to relay all that information back to the actual controller so here we can say make sure the view model is not actually nil so we're going to bind it with the guard and we can say delegate person following table view cell self did tap with the view model so let's see if these errors go away so it looks like they all went away now that we have this delegate relationship on here on the view controller what we can go ahead and do is for this cell we can say it's delegate itself and we just need to conform to that new protocol here so we're going to say extension on the view controller on the view controller and we want to extend the delegate here and implement that function we added so in here what we're going to go ahead and say is if view model dot currently following um we want to go ahead and update its actual value so so there's a couple ways you can go ahead and do this right so either you can update the model value here or one thing you can do is if we command click into this we can actually make this currently following mutable by making it a var so one thing we can do is if we come back to our view here whenever this button is tapped we can create a copy of the view model so let's do this whoops so we're here we're going to say this is the view model and then what we can do is var new view model is a copy of our view model now keep in mind it's a struct so it's not a reference type it's a value type and we can say the new viewmodels.currently following is going to be the inverse of v model currently following so if this is true this will not be false if this is false uh this will now be true and in this delegate function we can actually go ahead and pass in the new view model and here in the controller bit of it we can actually go ahead and save this into our data source suppliers in this case it would be this array of models right i'm not going to actually do that because the video has already gone fairly long but one thing that i'll also mention here is um now that we have gone ahead and changed this view model we can actually call this configure function again so here we can now say configure and we can pass in the new view model so here we can also say prepare for reuse so this will reset the cell and we can configure with the new view model so let's go ahead and just hit command r hit the play button to build and run and let's see what happens when we hit this we can see that it changes every single time that we click it which is pretty nifty and not only are we doing this in a reusable way where we're all we're doing is we're mutating the view model based on user interaction here but we're also relaying it back to our view controller and our view controller can now take that information and do what it wants with it right so in a real app like facebook maybe that's making a network call to save that information to our back end so i know this video is not fairly long but i just want to recap really quickly all we really did here is we have a controller that has a basic table view we have a person model so super important that you understand that this is the actual model where the majority of the data lives this is the data layer part of it right and then we have a custom cell that we created this is a subclass of a table view cell and then the new thing here which is the the root of all all of the stuff is a view model and by definition uh this is something that has this is a type of a model rather that has all the information to write a review nothing more nothing less so in this case we created with the model now notice the model had things on it like birth date age and all that other stuff that the view basically doesn't care about therefore we don't want the view model to necessarily have it then on the actual table view cell itself we configure it with the view model let me see where it is right down here and we also go ahead and save that model and the reason we do is because whenever we tap the button we mutate the view model because now that we've you know changed state we want to re-render the view we re-render it and then we also notify the controller via the delegate that hey the view model went ahead and changed you might want to update stuff and that's how you can get this to work and that's architecture which is fairly clean and separates out your concerns in the grand scheme of things so notice you can click back and forth and this is really really simple for the most part once you get the hang of it and extremely commonly used across ios design patterns so hopefully that all made sense i know it was kind of a lot definitely leave comments down below for any questions clarifications feedback concerns love hearing from you guys would love to help you out as much as i can make sure you destroy that like button as per usual for the youtube algorithm helps out with all the videos in future videos quite a bit hit subscribe while you're at it if you enjoyed this video and are excited for daily uploads i try to upload it almost every single day swift videos ios some objective c thrown in there this and that thanks for watching i will catch you guys in the next video
Info
Channel: iOS Academy
Views: 24,621
Rating: undefined out of 5
Keywords: swift 5 tutorial, swift 2020, swift, swift 5, swift tutorial, swift for beginners, swiftUI 2020, swift programming, swift basics, swift apps, make iPhone app, swift make first app, swift MVVM, swift model view viewModel, MVVM swift, swift 5 MVVM, model view view model swift, ios swift model view viewModel, MVVM 2020, swift 5 MVVM ios, iOS development MVVM, MVC vs MVVM, swift model view viewmodel, swift mvc example, swift MVVM example, ios swift MVVM, MVVM swift 2020, ios
Id: qzXJckVxE4w
Channel Id: undefined
Length: 35min 43sec (2143 seconds)
Published: Tue Nov 03 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.