10

I am fairly aware about difference between a value type and reference type in Swift and aware that value types are designed to be immutable usages. But structs in particular have ability to mutate themselves and that is my concern. How to effectively use these mutating struct value types so that they maintain their state or changes across.

My question is, in iOS app's MVVM design should view model be a class or a struct? As view model holds the model/list of model and these model instances can change over time (ex. view model gets more model instances from a web service request and adds into it's array of model), how does view controller's view model is updated with this change. Here is a pseudo example, but first some considerations and brief:

  • I am not using any bindings here. (No RxSwift).
  • No KVO, I am using delegation or completion handler design.

Example:

  • View controller has instance of view model. When it is appeared, it asks view model to fetch data from web service.
  • View model fires service, and get response in a completion handler closure
  • In this closure view model adds some model instances into it's array of models.
  • View model calls a completion handler of view controller to notify the success or error of service request.
  • View controller does some validation on view model and then perform UI action accordingly.

View Model:

 struct DummyViewModel {

  private var ints:[Int] = []

  var count: Int {
    return ints.count
  }

  init() {}

  mutating func fetchData(completionHandler:(NSError? ) -> Void) {
    Networking.getDataFromRemote() { response in
          self.ints.append(1)
          completionHandler(nil)
    }
  }
}

View Controller:

class DummyViewController: UIViewController{
  private var dummyViewModel: DummyViewModel?

  override func viewDidLoad() {
    super.viewDidLoad()

    /// Setup the view model
    dummyViewModel = DummyViewModel()
  }

  override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    loadData()
  }
}

private extension DummyViewController {

  func loadData() {
    dummyViewModel?.fetchData { error in
        if self.dummyViewModel?.count > 0 {
          print("View model updated")
        } else {
          print("View model is still same")
        }
      }
    }
}

In the above code when view model gets the response it adds data to it's array, but that change is never passed to the view controller because inside the closure it is the copy of view model that is updated not the view controller's model. So the question is how this change is passed to view controller?

Should I return the updated view model instance from the closure and in view controller's closure update it's instance of view model. But this also not gonna work as in view controller closure also I'll be updating the copy of view model??

How should we deal with this? One option is to make view model a class so that everything is a reference and we are updating the same instance everywhere. But as the same thing can happen with view model and model, models also will be classes. And as major portion of our apps are view controllers, view models and models all we are creating are classes. So we are really not using the power of value types here.

Any suggestions?

tarun_sharma
  • 761
  • 5
  • 22

0 Answers0