DesperateLearner
DesperateLearner

Reputation: 1175

Generics and ViewModels in Swift

I'm trying to simplify this following code with generics. Instead of conditional unwrapping for a type inside each of ChildViewOne, ChildViewTwo and ChildViewThree, can I achieve the same with generics?

struct UserInfo {
  let name: String
  let image: UIImage
}

enum SomeType {
  case typeOne
  case typeTwo
  case typeThree
}

struct ParentViewModel {
   let userInfo: UserInfo
   let type: SomeType

   var contentViewModel: Any {
    switch type {
      case .typeOne:
           return ChildViewModelOne(name: userInfo.name, type: type)
      case .typeTwo:
           return ChildViewModelTwo(image: userInfo.image, type: type)
      case .typeThree:
           return ChildViewModelThree(image: userInfo.image)
   }
}

struct ChildViewModelOne {
  let name: String
  let type: SomeType
}

struct ChildViewModelTwo {
  let image: UIImage
  let type: SomeType
}

struct ChildViewModelThree {
  let image: UIImage
}

ParentViewController will be injected with ParentViewModel.

class ParentViewController: UIViewController {
  let viewModel: ParentViewModel

  init(viewModel: ParentViewModel) {
    self.viewModel = viewModel
    super.init(bundle: nil, frame: nil)
  }

  // other required initializer

  func configureViewForType() {
     // Logic to handle subviews - ChildViewOne, ChildViewTwo & ChildViewThree
  }
}

This is what I tried so far: I introduced a protocol ConfigurableView

protocol ConfigurableView {
    associatedtype ViewModel
    func configure(model: ViewModel)
}

class ChildViewOne: UIView, ConfigurableView {
    func configure(model: ChildViewModelOne) {

    }

    typealias ViewModel = ChildViewModelOne
}

Update

How do I return this from ParentViewModel as a contentViewModel object in ParentViewModel? contentViewModel is to be called from func configureViewForType() inside ParentViewController where based on the type value inside ParentViewModel, I load the correct ChildView

Is there a better way to achieve this?

Upvotes: 3

Views: 635

Answers (1)

user652038
user652038

Reputation:

A View Model is not actually a "ViewModel". That idea is pervasive because not all languages have nested types. Instead, it is a View.Model.

class ChildViewOne: UIView {
  struct Model {
    let name: String
  }

  init?(model: Model, coder: NSCoder) {
    self.model = model
    super.init(coder: coder)
  }

  private let model: Model

  required init?(coder _: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

Upvotes: 1

Related Questions