Luke97
Luke97

Reputation: 539

Using MVVM with a complex Model structure

So i'm using the MVVM architecture and i've built a fairly complex view, so i decided to split the view up into separate classes and then use different view models for each of the separated view components. I'm also using coordinators (so MVVMC basically), i use the coordinator to setup my view controller and then create and inject the view models into the separate view components which are accessible through IBOutlets in my main view.

My problem is that i'm using CoreData and i'm trying to save a single NSManagedObject which has multiple relationships, however the relationship models are only available in my other view models which are connected to my separate view components. Is there a clean way i could give my main view model which is owned by my ViewController the relationship models from the other view models when a save button has been tapped from my main view. Or should i be thinking about using a delegation pattern maybe, to tell my other view models that the save button was tapped?

Upvotes: 1

Views: 558

Answers (1)

Y.Bonafons
Y.Bonafons

Reputation: 2349

So I think there is several possibilities. Here is how I try to manage almost similar situation, I hope it will help you in your thinking.

First I create protocols for my Viewmodels. For example:

protocol Child1ViewProtocol {
    func getFirstName () -> String
}

protocol Child2ViewProtocol {
    func getLastName () -> String
}

protocol MainViewProtocol {
    func getChildModel1 () -> Child1ViewProtocol
    func getChildModel2 () -> Child2ViewProtocol
    func getLanguage () -> String
    func saveButtonPressed ()
}

Then I create my ViewModel classes. Here is for the child, quite easy:

class Child1ViewModel: Child1ViewProtocol {
    var firstName: String?
    init(firstName: String?) {
        self.firstName = firstName
    }
    func getFirstName () -> String {
        return self.firstName ?? ""
    }
}

class Child2ViewModel: Child2ViewProtocol {
    var lastName: String?
    init(lastName: String?) {
        self.lastName = lastName
    }
    func getLastName () -> String {
        return self.lastName ?? ""
    }
}

And my MainViewModel which retain the child models so I can access to them when the function saveButtonPressed is called

class MainViewModel: MainViewProtocol {
    var user: User?
    var child1ViewModel: Child1ViewProtocol!
    var child2ViewModel: Child2ViewProtocol!

    init(child1ViewModel: Child1ViewProtocol,
         child2ViewModel: Child2ViewProtocol) {
        self.child1ViewModel = child1ViewModel
        self.child2ViewModel = child2ViewModel
    }
    func getChildModel1 () -> Child1ViewProtocol {
        return self.child1ViewModel
    }

    func getChildModel2 () -> Child2ViewProtocol {
        return self.child2ViewModel
    }

    func getLanguage () -> String {
        return self.user?.language ?? ""
    }

    func saveButtonPressed () {
        self.user?.firstName = self.child1ViewModel.getFirstName()
        self.user?.lastName = self.child2ViewModel.getLastName()
        // And save the user for example
    }
}

That means when you create your MainViewModel in your Coordinator, you need to create the childViewModels too and inject them in the MainViewModel. That also means you do not need to have a strong reference on the childViewModels in your view.

Upvotes: 2

Related Questions