Reputation: 1175
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
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