Reputation: 20379
Idea is to share the common code between UITableView
and UICollectionView
and their viewModels. So I have a baseCollectionsViewModel which is a generic class and looks like
class BaseCollectionsViewModel<T: BasicTrackDataExtractorProtocol> {
var baseTrackResponse: T?
...
}
Now I would like to have a BaseCollectionsView
which holds BaseCollectionsViewModel
. Because its a UITableView
and UICollectionView
I cant have a common base class among them so I decided to go in the direction of protocol to work around multiple inheritance
protocol BaseCollectionsViewProtocol {
associatedtype dataExtractorType: BasicTrackDataExtractorProtocol
var viewModel: BaseCollectionsViewModel<dataExtractorType>! { get }
//all other common properties and logic here
}
Finally when I try to use this protocol in my final class
final class TrackingTableViewModel: BaseCollectionsViewModel<TrackOrderV3> {
}
final class TrackingTableView: UITableView,BaseCollectionsViewProtocol {
var viewModel: TrackingTableViewModel!
typealias dataExtractorType = TrackOrderV3
//other code
}
Compiler complains that TrackingTableView
does not confirm to BaseCollectionsViewProtocol
and keeps adding
final class TrackingTableView: UITableView,BaseCollectionsViewProtocol {
var viewModel: BaseCollectionsViewModel<TrackOrderV3>!
typealias dataExtractorType = TrackOrderV3
Is this because BaseCollectionsViewModel<TrackOrderV3>
and TrackingTableViewModel
are invariant? Is there anyway I can resolve this problem with TypeErasure
?
If its not a protocol I could solve it as
class TestTableView<T: BasicTrackDataExtractorProtocol, U: BaseCollectionsViewModel<T>> {
var viewModel: U!
}
class TestTrackingTableView: TestTableView<TrackOrderV3, TrackingTableViewModel> {
func testViewModel() {
let _ = self.viewModel.numberOfRows
}
}
But the issue is now I cant say class TestTrackingTableView: TestTableView<TrackOrderV3, TrackingTableViewModel>, UITableView
because multiple inheritance is not allowed.
P.S: Sorry for the highly confusing title, couldn't come up with a better title, will change if someone can suggest a better one :)
Upvotes: 0
Views: 108
Reputation: 5073
What I would do is define a protocol for your view model:
protocol CollectionsViewModel {
associatedtype DataType: BasicTrackDataExtractorProtocol
var baseTrackResponse: DataType? { get }
}
Then implement a generic view model class that houses all of your common logic:
class BaseCollectionsViewModel<T: BasicTrackDataExtractorProtocol>: CollectionsViewModel {
typealias DataType = T
var baseTrackResponse: T?
}
Rather than setting the data model as a type constraint on the view protocol set the view model as a type constraint. This will give us greater flexibility down the road.
protocol BaseCollectionsViewProtocol {
associatedtype ViewModelType: CollectionsViewModel
var viewModel: ViewModelType! { get }
}
Now we can implement our final classes:
final class TrackingTableViewModel: BaseCollectionsViewModel<TrackOrderV3> {
}
final class TrackingTableView: UITableView, BaseCollectionsViewProtocol {
var viewModel: TrackingTableViewModel!
}
Upvotes: 2