Home > Mobile >  Generalizing multiple view models
Generalizing multiple view models

Time:11-26

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
    }
}
  • Related