我正在使用表格视图(类似于Facebook的Messenger),在该视图中我具有不同的单元格类型(图像,文本,视频等)。
我要存档的是,我想声明message model
的列表,然后配置 tableView ,以便该单元将由模型本身确定和配置。为了做到这一点,我需要以某种方式告诉model
它关联了哪个 UITableViewCell 类。基本上我想拥有这样的协议:
protocol ChatMessageDisplayable {
static var myCellType: UITableViewCell { get } //Defines the UITableViewCell class this model is associated with
func configure(cell: /*the associated cell type*/) // Let the model itself configure the cell.
}
然后在ViewController中,我将声明一个数组
messageModels = [ChatMessageDisplayable]
以及我的UITableViewDataSource实现:
public func numberOfSections(in tableView: UITableView) -> Int {
return messageModels.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let model = messageModel[indexPath.row]
let cellIdentifier = /* Name of the UITableViewCell this model is associated with */
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
model.configure(cell: cell)
return cell
}
反正我可以存档此目标吗?
答案 0 :(得分:1)
想象一下您的数据将是:
class TableViewModel {
let items: [Any] = [
User(name: "John Smith", imageName: "user3"),
"Hi, this is a message text. Tra la la. Tra la la.",
Bundle.main.url(forResource: "beach@2x", withExtension: "jpg")!,
User(name: "Jessica Wood", imageName: "user2"),
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
]
}
因此,通常我们会在tableView(_:cellForRowAt:)
的{{1}}方法中实现它
防止这种情况的一种方法是使用泛型类型。通用编程是避免样板代码的绝佳方法,并有助于在编译期间定义错误。
通用代码使您可以编写灵活,可重用的函数,并 可以与任何类型配合使用的类型,具体取决于您的要求 限定。您可以编写避免重复的代码并表达其内容 以清晰抽象的方式表达意图。 Apple Documentation
让我们制定每个单元格应遵循的第一个协议。
if let ...
现在,我们可以创建一个通用单元格配置器来配置表格单元格。
protocol ConfigurableCell {
associatedtype DataType
func configure(data: DataType)
}
//example of UserCell
class UserCell: UITableViewCell, ConfigurableCell {
@IBOutlet weak var avatarView: UIImageView!
@IBOutlet weak var userNameLabel: UILabel!
func configure(data user: User) {
avatarView.image = UIImage(named: user.imageName)
userNameLabel.text = user.name
}
}
现在,我们需要对ViewModel进行一些调整:
protocol CellConfigurator {
static var reuseId: String { get }
func configure(cell: UIView)
}
class TableCellConfigurator<CellType: ConfigurableCell, DataType>: CellConfigurator where CellType.DataType == DataType, CellType: UITableViewCell {
static var reuseId: String { return String(describing: CellType.self) }
let item: DataType
init(item: DataType) {
self.item = item
}
func configure(cell: UIView) {
(cell as! CellType).configure(data: item)
}
}
就这样!
您可以轻松添加新单元格,而无需编辑ViewController的代码。
让我们在表格视图中添加一个WarningCell。
1。符合ConfigurableCell协议。 2.在ViewModel的类中为该单元格添加TableCellConfigurator。
typealias UserCellConfigurator = TableCellConfigurator<UserCell, User>
typealias MessageCellConfigurator = TableCellConfigurator<MessageCell, String>
typealias ImageCellConfigurator = TableCellConfigurator<ImageCell, URL>
class TableViewModel {
let items: [CellConfigurator] = [
UserCellConfigurator(item: User(name: "John Smith", imageName: "user3")),
MessageCellConfigurator(item: "Hi, this is a message text. Tra la la. Tra la la."),
ImageCellConfigurator(item: Bundle.main.url(forResource: "beach@2x", withExtension: "jpg")!),
UserCellConfigurator(item: User(name: "Jessica Wood", imageName: "user2")),
MessageCellConfigurator(item: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."),
]
}
有关更多信息,请遵循此link