我正在尝试创建通用的CollectionView数据源。 我有两个协议,第一个 - 一些抽象单元格,第二个表示符合类可以由一些抽象单元格呈现,并且应该只包含引用该单元格的相关类型。它们的实现可能如下所示:
protocol EntityPresentingCell {
// entity that should be presented in this cell
associatedtype T
static var CellReuseID: String { get }
// takes object and fill UI with data
func populate(with object: T)
}
protocol CellPresentable {
// cell that should present this entity
// I need to constrain it
associatedtype Cell: EntityPresentingCell // where Cell.T == Self
}
class CollectionViewDataSource<T: CellPresentable>: NSObject, UICollectionViewDataSource {
var items: [T]
init(items: [T]) {
self.items = items
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: T.Cell.CellReuseID, for: indexPath)
// compiler error here since, obviously, T.Cell.T not constrained to T itself
(cell as! T.Cell).populate(with: items[indexPath.item])
return cell
}
}
在使用时它可能如下所示:
class SomeEntity: CellPresentable {
typealias Cell = SomeEntityCell
var someValue = "someValue"
}
class SomeEntityCell: EntityPresentingCell {
static var CellReuseID: String = "SomeID"
@IBOutlet weak var label: UILabel!
func populate(with object: SomeEntity) {
label.text = object.someValue
}
}
这段代码的问题在于我无法限制(因此在编译时确保)CellPresentable.Cell.T等于CellPresentable本身(如示例中所示)。可以清楚地看到编译器错误。
目标是制作纯编译时足够的代码,以证明该项目可以通过给定的单元格呈现(再次,在编译时),并且我不想强迫向下转换,或任何其他运行 - 时间检查。
有可能吗?如果是这样,怎么样?
UPD:David Rodrigues answer有效,但这意味着只有在我即将创建(T.Cell.T != T)
时才会显示不匹配CollectionViewDataSource
。当我定义我的实体与EntityPresentingCell
协议的一致性时,我希望它发生。换句话说,当我写
class SomeEntity: CellPresentable {
typealias Cell = SomeWrongEntityCell
var someValue = "someValue"
}
但不是在创建CollectionViewDataSource
实例时。确保细胞类型的实体责任,而不是CollectionViewDataSource
的创建者。
答案 0 :(得分:3)
您现在可以将protocol CellPresentable {
associatedtype Cell : EntityPresentingCell where Cell.T == Self
}
约束添加到关联类型中,因此您现在可以说:
where
目前,除了要求相关类型之外,还无法向关联类型添加任何进一步的约束。
但是,现在SE-0142: Permit where clauses to constrain associated types已被接受,在未来的Swift版本中,可以将protocol CellPresentable {
associatedtype Cell : EntityPresentingCell where Cell.T == Self
}
子句添加到关联类型。
你应能够说:
where T.Cell.T == T
虽然在实施此功能之前,添加通用约束float:left
的{{3}}可能与您即将获得的一样好。
答案 1 :(得分:1)
您可以将T.Cell.T
约束为T
。
class CollectionViewDataSource<T: CellPresentable>: NSObject, UICollectionViewDataSource where T.Cell.T == T