Sun*_*kas 9 generics ios swift
我想简化在UITableViewCell子类中调用"setup"方法的过程.但是,并非所有设置方法都相同,但它们的参数继承自相同类型.是否可以使用泛型或协议不必每次都抛出参数?
首先,我是一个像这样的cellForRow方法:
class DataSource<V : UIViewController, T: TableViewCellData, VM: ViewModel> : NSObject, UITableViewDataSource, UITableViewDelegate {
var dataCollection: TableViewDataCollection<T>!
var viewModel: VM!
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellData = dataCollection.object(for: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: cellData.identifier(), for: indexPath)
if let setupableCell = cell as? CellDataSetupable {
setupableCell.setup(with: cellData, viewModel: viewModel)
}
return cell
}
}
protocol CellDataSetupable : class {
func setup(with cellData: TableViewCellData, viewModel: ViewModel)
}
Run Code Online (Sandbox Code Playgroud)
我使用cellData和viewModel设置单元格.
在我的(很多)自定义UITableViewCell子类中:
extension BlurbTableViewCell : CellDataSetupable {
func setup(with cellData: TableViewCellData, viewModel: ViewModel) {
guard let cellData = cellData as? HomeViewTableViewCellData else { return }
guard let viewModel = viewModel as? HomeViewModel else { return }
// Use cellData and viewModel to setup cell appearance
}
}
Run Code Online (Sandbox Code Playgroud)
where HomeViewTableViewCellData的子类是TableViewCellData和
HomeViewModel的子类ViewModel
相反,我想删除警卫并直接写这样的东西:
extension BlurbTableViewCell : CellDataSetupable< {
func setup(with cellData: HomeViewTableViewCellData, viewModel: HomeViewModel) {
// Use cellData and viewModel to setup cell appearance
}
}
Run Code Online (Sandbox Code Playgroud)
尝试的解决方案(不起作用):
但是,我不能在协议上使用associatedtype/typealias,因为这会在cellForRow方法中对转换产生错误"Protocol ...只能用作通用约束,因为它具有Self或关联类型要求".我在使用继承自Storyboard中的泛型类的类时尝试了这种方法:"接口构建器文件中的未知类"
我也不能使用通用基类,因为接口构建器会崩溃:如何在Swift中创建通用协议?(另见下面的编辑2)
有什么想法或我必须和我的铸件一起生活吗?
编辑1: 在Nate Mann的建议下面我尝试了这段代码(注意我已经重命名了一些泛型类型):
// This works fine
extension TransactionTableViewCell : CellDataSetupable {
typealias CellData = HomeViewTableViewCellData
typealias VM = HomeViewModel
func setup(with cellData: CellData, viewModel: VM) {
//Setup cell appearance ...
}
}
Run Code Online (Sandbox Code Playgroud)
这行也可以正常工作:(注意额外的where子句)
class DataSource<VC : UIViewController, TVCD: TableViewCellData, VM: ViewModel, CDS: CellDataSetupable> : NSObject, UITableViewDataSource, UITableViewDelegate where CDS.TVCD == TVCD, CDS.VM == VM {
// ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellData = dataCollection.object(for: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: cellData.identifier(), for: indexPath)
if let setupableCell = cell as? CDS {
setupableCell.setup(with: cellData, viewModel: viewModel)
}
return cell
}
Run Code Online (Sandbox Code Playgroud)
但改变了
class HomeTableViewDataSource: DataSource<HomeViewController, HomeViewTableViewCellData, HomeViewModel> {
Run Code Online (Sandbox Code Playgroud)
至
class HomeTableViewDataSource: DataSource<HomeViewController, HomeViewTableViewCellData, HomeViewModel, CellDataSetupable> {
Run Code Online (Sandbox Code Playgroud)
给出这个错误:
Using 'CellDataSetupable' as a concrete type confirming to protocol 'CellDataSetupable' is not supported
Run Code Online (Sandbox Code Playgroud)
编辑2:使用UITableViewCell类的通用基类的具体版本是不可能的.请参阅为什么界面构建器不能使用UIView的具体通用子类?
我自己的想法是,目前不可能。
内特·曼的回答要求我指定一个CellDataSetupable我不想要的具体实现。
timaktimak 的答案要么需要具体的实现,要么需要 UIView 的子类化。
| 归档时间: |
|
| 查看次数: |
1003 次 |
| 最近记录: |