I have written a couple of view models for my SwiftUI project. It turns out that they share quite a lot of properties and code and I wanted to pull this code into a generic view model and then user class inheritance to specialize the real view models. Unfortunately this turns out quite difficult. Here's a simplified example:
class viewModelA: ObservableObject {
enum Animal {
case cat
case dog
}
@published var selected: Animal?
func select(_ animal: Animal?) {
self.selected = animal
}
...
}
class viewModelB: ObservableObject {
enum Animal {
case lion
case tiger
}
@published var selected: Animal?
func select(_ animal: Animal?) {
self.selected = animal
}
...
}
The first thing I've tried is to create a protocol and use a protocol with an associatedtype for Animal, but then I struggled with the property that has @published. Swift doesn't allow to have property wrappers in protocols...
How could I generalize those 2 classes?
CodePudding user response:
Here is first possible approach (protocol-based):
protocol AnimalModel: ObservableObject {
associatedtype Animal
var selected: Animal? { get set }
}
class ViewModelA: AnimalModel {
enum Animal {
case cat
case dog
}
@Published var selected: ViewModelA.Animal?
}
class ViewModelB: AnimalModel {
enum Animal {
case lion
case tiger
}
@Published var selected: ViewModelB.Animal?
}
and here is second one (inheritance-based):
class ViewModel<Animal>: ObservableObject {
@Published var selected: Animal?
}
class ViewModelA: ViewModel<ViewModelA.Animal> {
enum Animal {
case cat
case dog
}
}
class ViewModelB: ViewModel<ViewModelB.Animal> {
enum Animal {
case lion
case tiger
}
}