SwiftUI MVVM | A Realistic Example

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on everybody it's your boy kilo loco and today i'm gonna be covering mvvm and that's gonna be specifically with swift ui so luckily swift ui kind of sets it up to where you kind of need to work with mvvm there's not a whole lot to think about you might have already been implementing it but i'm going to show you how to get started with mvvm i'm going to show you how i implement it and show you some of the use cases that i run into and how i work around them so let's go ahead and jump right on in so as you can see we are starting off with this basic project where i have this user's view and it's pretty much the same as the content view when you start off a new swift ui project now what we want to do in our users view is display a list of users now generally you would get those users back from your backend right you would do some type of query and then you would get those users and then you would display them now the way that i'm going to do this is i'm going to be getting my users from my view model which means my view model is going to be the place where i keep all my business logic all the the stuff that makes makes the app actually work and do the thing that is supposed to be doing right and that's what we're going to use the view model for and the view is simply going to be a stupid you know view that just simply displays whatever is given to it by the view model so the first thing that we want to do is actually create that viewmodel class now before i do that i want to say that i'm going to do it a little bit differently than what you might be used to seeing and you can feel free to do this however you want so let me show you how i do it alright so as you can see i created an extension on the user's view and in that extension i created the class called view model this means that this view model is scoped specifically to a user's view so if you wanted to actually create an instance of this view model it would have to be user's view users view dot view model and the reason why i do this is because the likelihood of you using the same view model for different views is kind of uncommon i haven't really found a practical use case of actually doing this when i was working with ui kit so if you were to try to do this with swift ui i just don't see it as being something that's going to come up a whole lot so that's why i choose to scope it this way you can obviously create something called user's view view model which is you know fine but um you know i choose to do it this way because then it keeps it consistent and it's always going to be a view model inside of a v of a view that has state so then there's that consistency there that every time there's a user's view or whenever there's a view that has state it's going to have a property on it called view model which is going to be of type it's view model whatever the scoped view model is so i'm just throwing that out there so then what i want to do is i want to make sure that this is an observable object because we're going to actually implement it as a state object it needs to persist past each iteration of the creation of the view and then we have this published property which is just simply going to be the users essentially where we're going to be getting our data from to populate our view next what we need to do is we need to actually create a list in our users view that is taking the data from the view model and displaying it into a list alright so as you can see i created an instance of our view model which is just simply view model or you can do self dot view model or if you really wanted it to be explicit then you can do you know users view dot view model any of these things work whatever you feel is best but i'm just going to keep it as view model i feel like it's clean like that like i said state object we're creating that list grabbing the users each user is going to display a name of text now it's not showing anything in our preview and that's simply because there's nothing in the users array so now we need to create a function that's going to get those users now this is the part where we would actually do a networking request and go up and go get those users from the end right and what you would normally want to do to make sure that your data is nice and clean and properly separated is to have a class that is going to do that for you so as you can see right here i have this app data service that i'm going to use in order to get my users so it has a function that has a callback called completion and whenever that completion is done it's simply going to pass us an array of those users so let's go ahead and use that so jumping back over to the user's view let's go ahead and get an instance of our data service all right so as you can see we have our data service right here which is the instance of app data service right and then in our get users function we're going to do data service dot get users which is then going to update the users so now what we need to do is we just need to make sure that we're calling this function from our body and we're going to do that on up here on the list all right and there it is as you can see here we are doing on appear and we're going to perform viewmodel.getusers now luckily we're working with dummy data and we're able to see the data right here kyle jamal and lee and all this data is coming from our app data service now in reality what would normally happen is you're going to go up to the api and then it's going to return some data now in order to kind of um show that show that like what is kind of normal to happen i'm going to wrap this in a dispatch queue put it back on the main thread and you're going to see that our preview will not be able to actually show that data all right so as you can see got the dispatch queue going to the main thread and um we put our completion inside there now if we go back over to our users view and if we resume our preview you're going to notice that all the data disappears and the reason for that is because it's not the preview isn't able to just understand what's going to happen once it gets past the dispatch queue and things like that so in order to continue making our preview work with this system what we want to do is we actually want to be able to inject a view model into our users view so instead of initializing the view model like this we're going to initialize it in the initializer so let's go ahead and make some changes all right so as you can see what i did was i updated instead of initializing the view model right here i say it's of type view model and then in the initializer i'm passing in a view model and what happens when you have a state object is it gives you this um this other property that which is going to be underscore whatever the name of the property is so if i called it view model it'd be underscore view model if i called it state it'd be underscore state and all it's going to do is it's going to allow us to pass the state object to this object right here and we can initialize that state object with this view model that's being passed into our initializer and everything's going to work essentially as it was before now the benefit here is that we are able to pass in a view model at the preview level so if we just go ahead and create a view model with some users in it now we can see that there is a view model being passed to this user's view so we created that user created the view model pass the user in as an array of a single user into that view model and then pass the view model so now if i resume my my view well it's going to crash and the reason why i crashed is because back over here in our app object we actually can't create this uh user's view with an empty initializer now we need to fix it so that we're creating a view model like this but this kind of looks ugly so instead of doing it here what i'll do is i'll go back over to our initializer in our users view and i'll give it a default value which is just going to be a knit so it's going to initialize a view model just a regular view model and then if we go back over here we're gonna notice that there's no errors and if we try to try again on our preview we're gonna see that the dummy user shows up like so so this is essentially how you're going to be working with view models now let's keep going let's make it a little bit more intermediate to advanced levels of scenarios that you're going to be running into now the problem that we have so far is that we're actually using the app data service which which is fine you know you can use it like this but it doesn't follow like the clean principles and everybody wants to just make everything like protocol oriented whatever that's fine so in order to get past that what we want to do is we want to make our data service be a protocol and that will make it so that we're not tied specifically to the app data service in case we want to change the implementation there so what we're going to do is we're going to create a new protocol called data service and instead of working directly with the app data service we'll just be working with anything that conforms to the data service so let's go back over to our app data service let's create a protocol that has the get users function in it alright so as you can see we created this data service protocol and it has a function same exact signature i just copied and pasted it and our app data service now conforms to that data service so let's go back over to our users view model and what we'll do is instead of making data service like this we'll have it conform or have it be of type data service like that and data service will still be able to do get users and based off of whatever object was initialized for this data service will do the implementation in our case the we're going to be using the app data service so what we'll do for the view model is we'll create an initializer that allows us to pass in a data service so there you go as you can see there's no more errors on the view model but now we have a similar problem to what we did in the app object where we can't just simply create a view model with with an empty initializer it needs to be passed a data service so what we'll do is we'll give it a default argument of app data service so now if we do an initializer like this it's automatically going to assume that you want a app data service but it also gives us the flexibility to start testing with like a mock data service or whatever you want to do there and all this functionality will still work so that's really good and if you press resume you're going to notice that that the preview is still working just as it did before now the last thing that i want to show you is just going over how you would test something like this so just to make a very basic example what we'll do is we'll go over to the test area and we're going to make sure that our app is imported so testable import and then whatever your app name is and we want to have the system under test so it's going to be sot and it's going to be our view model all right so as you can see we have sot which is system under test and then we have our users view dot view model which is going to be what we're testing and in the setup and the tear down for the setup we're going to set the sot to right now i just have it as dot init for the tear down i'm just making that sot nil now when you're working with tests you're going to want to use mock services so if we try to use this especially if it was connected to a backend it's not going to work and that's primarily because we have dispatch queue and that's going to kind of throw some things off things aren't going to be executed immediately in line so what we'll do is we'll real quick create a mock data service just so that we can pass it into our view model so you can see what that's kind of like and then we can go ahead with the test all right so as you can see we created a very basic mock data service normally put in a different file but hey whatever and then it conforms to data service and we're going to implement the gate users in this case we're just going to have one user which is going to be 1 and the name is going to be kilo logo we're going to then initialize our view model so we can do it this way and just to make sure that it's not confusing i can do it a different way we initialize that view model with a data service we'll pass in an instance of our mock data service or we could create it up here it doesn't really matter this is just an example but essentially what's going to happen is we're now going to have a mock data service so what we want to test on our view model is it only has one function let's go ahead and double check that whenever we do a get users that it's going to have some type of update to the user's property on our view model so i'll create a function called test get users alright so as you can see i created this new test function called test gate users and we're going to start it off by doing an assert true making sure that sot.users our viewmodel users is empty when it starts out then we're going to call getusers now remember we're going to be using this sot which was created with a mock data service and our mock data service is going to be providing a single user so in my test i could do xct assert equal sot.users.count the user's count is going to be equal to one which is just going to be kilo logo i could also do any number of things to test that user make sure the id is um you know one whatever test it however you want but let's go ahead and test this class again and make sure everything's working as expected we run it and as you can see we get the little green check mark next to our test saying that it was successful so that's pretty much it that i want to show you a couple of other things that i'll just mention right off the top without going over it too much back over here in the users view there's going to be times where you're going to want to have like data service maybe it's provided by a data manager in that case what i would recommend is using maybe a singletons for your data manager you would have a singleton for your data manager and then you would just simply access the the singleton from right here as the initial argument so that's one thing that you might want to see also the same thing with if you want to do injection through the view let's say that you had to inject some type of object into the user's view then you could create the initializer and pass that object in here the same way the same way that we did with the view model but let's say we wanted to inject something into that view model well you could do it that way or you could create some type of other function where it would be like funk configure and then it'll be like with something and then you would just pass in whatever that something is here and then you could you know inject it into your view model that way so those are a couple of other things that i ran into that you might be interested in um if you want more in depth about mvvm or any other topic please leave a comment down below be very descriptive with your comments let me know exactly what you're looking to see so that i can have a better idea of how to present the information in the tutorial it's going to really help me in 2021 make sure that my content is right on point with what you're looking to have covered so that's going to be it for today i hope you learned something new i hope you hope you enjoyed the video and if you did make sure you give it a like make sure you subscribe i would really appreciate it it fills my heart with joy a whole lot so like i said that's it have a great day and go out there and keep coding passionately
Info
Channel: Kilo Loco
Views: 32,452
Rating: undefined out of 5
Keywords: swiftui, swiftui mvvm, swiftui mvvm tutorial, swiftui mvvm example, swiftui mvvm architecture, swiftui mvvm networking, swiftui mvvm testing, swiftui testing, swiftui mvvm simple example, swiftui mvvm folder structure, swift swiftui, swift mvvm, swift mvvm tutorial, swift mvvm example, ios mvvm, ios mvvm tutorial, ios mvvm example, swiftui state object, swiftui mvvm state object, swiftui unit testing, swiftui dependency injection, swiftui best practices, swiftui tutorial
Id: bdqEcpppAMc
Channel Id: undefined
Length: 16min 46sec (1006 seconds)
Published: Wed Dec 23 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.