0

I'm new to SwiftUI architecture especially when using MVVM. Currently I've got the following situation that I try to solve using MVVM. I struggle to understand the boundaries of a view model and how to solve the data handling part for it.

Let's give an example: the properties of the following domain model should be changed throughout a sequence of different NavigationViews, think of it as a wizard.

The struct representing this domain model looks like this:

class BusModel: Identifiable {
  let id: UUID
  var name: String
  var drivers: [DriverModel]
}

class DriverModel: Identifiable {
  let id: UUID
  var firstName: String
  var lastName: String
  var toursToDrive: [TourToDriveModel]
}

class TourToDriveModel: Identifiable {
  let id: UUID
  var dayOfTheWeek: Int
  var tour: TourModel
}

class TourModel: Identifiable {
  let id: UUID
  let label: String
}

As you see, the domain model has some sort of hierarchy: BusModel contains a list of DriverModel contains a list of ToursToDriveModel contains a TourModel

The purpose of the first NavigationView is to make changing the BusModel.name field possible. After clicking the next button, the list of drivers getting displayed, represented using NavigationLinks. There it should be possible to add a new driver or update the existing ones. So clicking on a list item navigates the user to the next view, presenting the data of those DriverModel. There it should be possible to change the drivers firstName and lastName and should show it's toursToDrive presented in a list as well. Changing a tourToDrive follows the same navigation principle as described for the driver.

So my question is: after all every view changes some properties of the underlying BusModel object and I don't know what a view model in this context would look like. Should the view model be related to all those single views or should every view has it's own dedicated view model?

Currently my view model spans the whole set of views, where every view changes to related properties of the view model. But I don't think that's correct because the view model holds every logic of every single view and if the relationship would be 1:1 of view and view model, those logics would be scoped to the distinct view they belong to.

So I guess, putting the domain model into an environment object which can be used within every distinct view model would be a better choice?

Another problem I have right now is, that the BusModel fields are exposed as @Published properties, so it looks something like this:

class AlterBusViewModel: ObservableObject {
  @Published var name: String
  @Published var drivers: [DriverModel]
}

But if DriverModel.firstname gets updated, the view model doesn't propagate the changes to ancestor views as well, because it's some sort of nested property I guess? Even if the view model would be divided into view related view models, this problem persists from my point of view. How could this be solved as well?

Finally the domain model and data handling gets replaced by core data later on, but for now I would like to solve it by using a class representing the domain model at runtime which should be updated subsequently.

If there are any questions, feel free to ask, I will provide more info as soon as possible!

Many thanks in advice.

andreas.teich
  • 789
  • 1
  • 12
  • 22
  • Make all your models as `struct` not `class` and then your question will be resolved automatically. – Asperi Nov 27 '21 at 13:44
  • https://stackoverflow.com/questions/70016175/foreach-not-properly-updating-with-dynamic-content-swiftui/70130763#70130763 – lorem ipsum Nov 27 '21 at 13:46
  • Did not work as well because the classes where structs at the beginning. – andreas.teich Nov 27 '21 at 13:48
  • One view model per view is what you should aim for. You model object(s) should not be an environment object. – Joakim Danielson Nov 27 '21 at 13:59
  • @asperi what do you think? – andreas.teich Nov 27 '21 at 14:14
  • If you tried having your models as `structs` and it didn't work, you have some other error in your code. Please post a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – Yrb Nov 27 '21 at 17:35
  • Okay, I‘ll try again. But view models and view 1:1 is best practice? So having for every view a dedicated view Model I mean. – andreas.teich Nov 27 '21 at 17:45
  • Not necessarily. You could have different views displaying the same data in different ways. Take for example a set of numeric data. One view may display a table of the numbers, another view may show a graph of the numbers, and yet another view may show an image that embodies the numbers (think weather app). You would not write different view models for each of those views since they take the same data. – Yrb Nov 28 '21 at 20:21

0 Answers0