我知道this post提出与我相同的问题,但是没有答案和陈旧,所以我认为id在这里刷新它。
//: Playground - noun: a place where people can play
import UIKit
protocol BaseViewModel { }
protocol SomeCellViewModelInterface : BaseViewModel { }
protocol AnotherCellViewModelInterface : BaseViewModel { }
protocol BaseCell {
typealias T
func configure(viewmodel: T)
}
//
class someCell : UIView, BaseCell {
typealias T = SomeCellViewModelInterface
func configure(viewmodel: T) {
// awesome
}
}
class someOtherCell : UIView, BaseCell {
typealias T = AnotherCellViewModelInterface
func configure(viewmodel: T) {
// do stuff
}
}
// the concrete implementations of viewmodels and actually using this UI is ultimatley in another .framework
class ConcreteSomeCellVM : SomeCellViewModelInterface { }
class ConcreteAnotherCellVM : AnotherCellViewModelInterface { }
var viewModel = ConcreteSomeCellVM()
let views: [UIView] = [someCell(), someOtherCell(), UIView()]
这是我需要的一个基本例子,但它说明了这一点
for v in views {
// A
if let cell = v as? someCell {
cell.configure(viewModel)
}
// B
if let cell = v as? BaseCell {
cell.configure(viewModel)
}
}
Block A有效,但需要知道具体的单元格类,所以如果我有一个包含许多不同单元格的列表,有些我不知道具体类型的单元格会起作用。
B区块抛出此错误:
错误:协议' BaseCell'只能用作通用约束,因为它具有Self或关联类型要求
有没有办法可以实现Block B?
答案 0 :(得分:0)
有没有办法可以实现Block B?
我不这么认为。假装您是编译器并考虑如何在BaseCell中为configure
创建代码。
如何在configure
的实例上调用BaseCell
,知道它可能真的是someCell
或someOtherCell
,每个实例都将参数限制为不同的类型?例如
func doSomethingWithACell(foo: BaseCell)
{
foo.configure(??? what can you put here?)
}
为了实现你真正想要的东西,我认为你需要摆脱类型别名并做出如下声明:
protocol BaseCell {
func configure(viewmodel: BaseViewModel)
}
在每个课程中,他们都需要处理viewModel
类型不正确的情况。
答案 1 :(得分:0)
我发布了迄今为止我提出的更新,一种答案,虽然它不理想我已将配置方法更改为如下所示:
func configure<T where T : BaseViewModel>(viewmodel: T)
因此,当我配置这些视图时,我不必知道每个视图的具体类:
for v in views {
if let cell = v as? BaseCell {
cell.configure(viewModel)
}
}
需要注意的是,您的具体单元需要转换视图模型类型:
func configure<T : BaseViewModel>(viewmodel: T) {
if let vm = viewmodel as SomeCellViewModelInterface {
vm.doSomething()
}
}
哪个更好但仍然不理想,因为演员阵容仍然需要在单元格中发生。