How I Structure My SwiftUI iOS MVVM Apps (General Code Overview & Folder Structure)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone welcome to another video and in this video i'm going to be talking about how i set up my swift ui apps with mvvm architecture so i'm going to talk about where i would put my api service where i'd put core data if i was using that and the folder structure i would use and it's a really contrived example we've got this user profile view with this text that we are going to populate with a user's username as if it were coming from a network and one thing to say before we get started is that you're going to see lots of different opinions about how to approach mvvm so it's important that you look at several different sources and you use something that you're comfortable with and this is just my approach so let's get started and the first thing i would do with any new project is i would create a new group called views and i would obviously drag in any views into here and then as the app grows i'm going to create new subgroups so for this one i would create a user sub group and i would drag anything related to the user which is a view into this group and then you can segment out the app quite nicely like this and the second main group i'm going to be creating is called view models and i would normally have one viewmodel per main view and i'm going to create a new file here for the sake of the example i'm going to call this user profile viewmodel and let's create a final class user profile viewmodel and let's make it an observable object so we can have this at published var username property and this is what is going to be updated from our api and what we're going to display in our view so what we need to do is that any view model that requires data is going to be using something called a repository so let's create a new group and this is going to be called repositories and let's create a new file called user repository and inside our user repository file i'm going to create a protocol user repository protocol and inside our protocol we're going to have a function fetch user with a completion which will give us back a user and the reason i'm creating a protocol for our user repository is that when we come to test our viewmodels we want to be able to mock out this user repository and pass in our own mock user repository and this will allow us to isolate the viewmodel when we test so we can basically override this fetch user function and return our mock user that we want to our test so we know that we're only testing the view model and we're not relying on a network or something like that in our testing so this is complaining about the lack of a user here so let's go and create a new group which is going to house all of our models and we're going to create a new file called user.swift and this is going to be a struct user with one property username and if we come back to our user repository here this will now compile and we can create our user repository which is going to implement that protocol and then we can implement our fetch user function and now we need to actually go and get our user so we're going to fetch it from an api service but we could easily look at something like a storage service which would hit a core data implementation so you might see something like this where we have an api service which will be a user api service protocol or you can have a storage service which might be a user storage service protocol and maybe that looks at user defaults maybe it looks a cool data or you can use these in tandem so you might be using these together but for this example we are going to be just using the api service just to get this flow across and what we need to do is we need to actually go and create this so let's create a new group which is going to be where we put all of our services and we can have a new file here called user api service and again a protocol to help with testing fetch user and then we have our class below and this is going to complete with our fake user which we're pretending is from the network and the username is going to be james and we're going to come back to our user repository now and we're going to inject our api service through the initializer here so let's type init api service and then we're going to give it a default argument of our concrete class user api service and then we're going to assign that to api service there and in our fetch user function now we can hit our api service and we can call fetch user now you might be wondering why are we creating a repository which has exactly the same method signature as our service and the reason for that is we want to keep the api service completely related to network activity and the repository here is going to potentially be using a storage service to interplay with this api service or perhaps a caching layer for example so let's come down here and let's complete this so we can just pass the completion through here and we can come back to our view model and what we're going to do is we're going to have a function on appear and this is what will be called when the view appears and we're gonna have to call our repository to fetch that user and set our username so let's declare our privatelet repository and this is gonna be our user repository protocol and let's have our initializer here which we'll inject the repository into and again this default argument and remember in the test we're going to replace that with our mock user repository and in our on appear here we're just going to call repository fetch user and then we're going to take that user and we're going to set our username to be user.username and then in our view itself we can now come in and declare our viewmodel and this is going to be an at state object private for viewmodel equals userviewmodel i'll use a profile viewmodel and let's give the text that username and then the final thing we need to do is call on appear and we're going to say viewmodel.on appear so now when on appear is called our repository we'll go and fetch the user we'll set our username property which will update our view and hopefully display james as we have returned in a mock form from our api service so we're running it now and there you go there's james so this is just an example of a flow i might use in one of my apps and there would be other groups here as well maybe one for network maybe one for database that kind of thing and the general idea is just to keep everything structured and it's clear where things need to go so if you did find that you got some value out of this video please do give it a thumbs up and subscribe to the channel if you haven't already if you don't agree with my approach please do give a comment down below and tell me what you would do differently and i will see you for the next one
Info
Channel: James Haville
Views: 8,643
Rating: undefined out of 5
Keywords:
Id: i66xMrpIgYA
Channel Id: undefined
Length: 8min 51sec (531 seconds)
Published: Tue Mar 30 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.