简体   繁体   English

如何使用关联类型解析协议中的泛型属性?

[英]How to resolve generic property in protocol with associatedtype?

Idea is to share the common code between UITableView and UICollectionView and their viewModels.想法是在UITableViewUICollectionView及其视图模型之间共享公共代码。 So I have a baseCollectionsViewModel which is a generic class and looks like所以我有一个 baseCollectionsViewModel 它是一个通用的 class 看起来像

class BaseCollectionsViewModel<T: BasicTrackDataExtractorProtocol> {
    var baseTrackResponse: T?
    ...
}

Now I would like to have a BaseCollectionsView which holds BaseCollectionsViewModel .现在我想要一个包含BaseCollectionsViewBaseCollectionsViewModel 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 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最后,当我尝试在我的最终 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编译器抱怨TrackingTableView没有向BaseCollectionsViewProtocol确认并不断添加

final class TrackingTableView: UITableView,BaseCollectionsViewProtocol {
    var viewModel: BaseCollectionsViewModel<TrackOrderV3>!
    typealias dataExtractorType = TrackOrderV3

Is this because BaseCollectionsViewModel<TrackOrderV3> and TrackingTableViewModel are invariant?这是因为BaseCollectionsViewModel<TrackOrderV3>TrackingTableViewModel是不变的吗? Is there anyway I can resolve this problem with TypeErasure ?无论如何我可以用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.但问题是现在我不能说class TestTrackingTableView: TestTableView<TrackOrderV3, TrackingTableViewModel>, UITableView因为多个 Z5FED3411FAF832174EF1F040028B2C21 是不允许的。

PS: Sorry for the highly confusing title, couldn't come up with a better title, will change if someone can suggest a better one:) PS:抱歉标题很混乱,想不出更好的标题,如果有人能推荐一个更好的,会改变的:)

What I would do is define a protocol for your view model:我要做的是为您的视图 model 定义一个协议:

protocol CollectionsViewModel {
    associatedtype DataType: BasicTrackDataExtractorProtocol
    var baseTrackResponse: DataType? { get }
}

Then implement a generic view model class that houses all of your common logic:然后实现一个包含所有常见逻辑的通用视图 model class:

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.与其将数据 model 设置为视图协议的类型约束,不如将视图 model 设置为类型约束。 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!
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM