我一直在尝试做一些允许用户将特定模型“附加”到特定单元格的代码。我打算用协议和associatedType
方法做到这一点。
这是计划:
单元格可以显示数据时符合MTZSectionRowConfigurable
,但它们不一定需要:
public protocol MTZSectionRowConfigurable {
associatedtype T: MTZSectionRowModel
func configure(with model: T?)
}
通过使用typealias
,他们允许用户定义他们将代表哪个模型:
class SignOutCell: UITableViewCell, MTZSectionRowConfigurable {
typealias T = SignOutModel
var redLabel: UILabel!
// ...
func configure(with model: SignOutCellModel?) {
self.redLabel.text = model?.text
}
}
模型只需符合MTZSectionRowModel
即可明确声明兼容性。
但是,由于代表模型是可选的,我需要在调用configure方法之前检查单元格是否支持它们。这是在cellForRowAtIndexPath:
if let cell = cell as? MTZSectionRowConfigurable {
cell.configure(with: sectionRow.model)
}
在上面的示例中,sectionRow.model
属于MTZSectionRowModel?
类型。
上面的代码无法编译。它产生了臭名昭着的:
“协议'MTZSectionRowConfigurable'只能用作通用约束,因为它具有Self或相关类型要求”
我试图检查单元格是否也响应#selector
,但不幸的是同样的错误也适用。
有没有办法让这段代码有效?我错过了什么吗?我可以删除associatedType
,使用广泛的MTZSectionRowModel
在每个单元格上实现方法,但是我需要在每个实现中进行转换,但在我看来这不是最佳解决方案。
答案 0 :(得分:0)
我知道你要做什么,我自己做了。但是,它比你现在所做的更为复杂。你在Andy Matuschak的gist中找到答案。
为了与SO答案的最佳实践保持一致,我将解释为什么这样做。让我们从结束开始吧。 cellForRow...
这是objc func
,需要返回UITableViewCell?
。所以我们已经知道,我们将在某些时候丢失类型信息(即你的SignOutCell
类不是返回的,它是它的超类,UITableViewCell
)。鉴于我们最终得到了UITableViewCell
,我们如何做您想做的事情并生成SignOutCell
并进行配置?答案在于定义安迪在他的要点(在此链接)中描述的CellFactory
中的完成处理程序。然后他使用bridgedDataSource
从一种细胞类型转换为另一种细胞类型。我自定义了他的代码,允许根据输入参数返回4种不同类型的单元格。例如,我的UITableViewController
可能包含4个UITableViewCell
项,每个项的布局和数据模型都非常不同。我会参数化CellFactory
以接受enum CellType
,其中我预先定义了4种类型。然后,在单元工厂中,我使用switch cellType
来设置单元格(此时我拥有单元格和模型数据的所有类型信息)。最后,bridgedDataSource
返回良性UITableViewCell
,使UIKit
非常高兴,并且具备我需要的所有品质。安迪所依赖的一个基本概念是分解。我相信他有一个YouTube视频,或者在他的网站上有一个视频,他可以通过这个视频。如果我这样做的话,我会看看能否找到并更新答案。