繁体   English   中英

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

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

想法是在UITableViewUICollectionView及其视图模型之间共享公共代码。 所以我有一个 baseCollectionsViewModel 它是一个通用的 class 看起来像

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

现在我想要一个包含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

protocol BaseCollectionsViewProtocol {
    associatedtype dataExtractorType: BasicTrackDataExtractorProtocol
    var viewModel: BaseCollectionsViewModel<dataExtractorType>! { get }
    //all other common properties and logic here
}

最后,当我尝试在我的最终 class 中使用此协议时

final class TrackingTableViewModel: BaseCollectionsViewModel<TrackOrderV3> {
     
}

final class TrackingTableView: UITableView,BaseCollectionsViewProtocol {
    var viewModel: TrackingTableViewModel!
    typealias dataExtractorType = TrackOrderV3
    //other code
}

编译器抱怨TrackingTableView没有向BaseCollectionsViewProtocol确认并不断添加

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

这是因为BaseCollectionsViewModel<TrackOrderV3>TrackingTableViewModel是不变的吗? 无论如何我可以用TypeErasure解决这个问题吗?

如果它不是协议,我可以将其解决为

class TestTableView<T: BasicTrackDataExtractorProtocol, U: BaseCollectionsViewModel<T>> {
    var viewModel: U!
}

class TestTrackingTableView: TestTableView<TrackOrderV3, TrackingTableViewModel> {
    func testViewModel() {
        let _ = self.viewModel.numberOfRows
    }
}

但问题是现在我不能说class TestTrackingTableView: TestTableView<TrackOrderV3, TrackingTableViewModel>, UITableView因为多个 Z5FED3411FAF832174EF1F040028B2C21 是不允许的。

PS:抱歉标题很混乱,想不出更好的标题,如果有人能推荐一个更好的,会改变的:)

我要做的是为您的视图 model 定义一个协议:

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

然后实现一个包含所有常见逻辑的通用视图 model class:

class BaseCollectionsViewModel<T: BasicTrackDataExtractorProtocol>: CollectionsViewModel {
    typealias DataType = T
    var baseTrackResponse: T?
}

与其将数据 model 设置为视图协议的类型约束,不如将视图 model 设置为类型约束。 这将为我们提供更大的灵活性。

protocol BaseCollectionsViewProtocol {
    associatedtype ViewModelType: CollectionsViewModel
    var viewModel: ViewModelType! { get }
}

现在我们可以实现我们的最终类:

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