I want to make a generic TableView DataSource class, that contains an array of ConfigureModel
:
protocol ConfigureModel {
associatedtype ModelType
var name: String { get set }
var modelDescription: String { get }
}
I also want the TableView cell to be generic:
class ConfigureCell<ConfigureType>: UITableViewCell, Configure {
func configure<Model: ConfigureModel>(with value: Model) where ConfigureType == Model.ModelType {
let description = value.modelDescription
print("ConfigureCell description: \(description)")
}
}
so I made ConfigureCell
adopt the generic Configure
protocol:
protocol Configure {
associatedtype ConfigureType
func configure<Model: ConfigureModel>(with value: Model) where Model.ModelType == ConfigureType
}
Now I can make a model adopt the ConfigureModel
protocol to be able to be used in the ConfigureCell
class:
struct Tag {
....
}
extension Tag: ConfigureModel {
typealias ModelType = Tag
}
This works fine. Now to make the ObjectDataSource
generic:
class ObjectDataSource<T: ConfigureModel>: NSObject, UITableViewDataSource, UITableViewDelegate {
var values: [T] = []
....
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = self.values[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "TagCell", for: indexPath) as! ConfigureCell<T>
cell.configure(with: item)
and here I have a problem that I have tried for many hours to solve. The last cell.configure(with: item
statement Xcode is showing the error: Instance method 'configure(with:)' requires the types 'T' and 'T.T' be equivalent
I understand that I have to make a generic where clause in the class, but I have trouble finding out what that should be.
class ObjectDataSource<T: ConfigureModel>: NSObject, UITableViewDataSource, UITableViewDelegate
where T == ???? {
I have made a Xcode Playground which works, but the commented out parts doesn't work. You can get it here: GenericDataSource Xcode PlayGround
I also want the TableView cell to be generic
You simply don't need that. You already have defined the configure(with:)
method to be a generic one. No need to make the class itself a generic one.
Given the above statement, if you're okay with it, here will be your implementation as simple as:
class ConfigureCell: UITableViewCell {
func configure<Model: ConfigureModel>(with value: Model) {
let description = value.modelDescription()
print("ConfigureCell description: \(description)")
}
}
class ObjectDataSource<T: ConfigureModel>: NSObject, UITableViewDataSource {
var values: [T] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return values.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = self.values[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "TagCell", for: indexPath) as! ConfigureCell
cell.configure(with: item)
return cell
}
}