I've written an extension to easily dequeue table view cells of a certain type:
class RedCell: UITableViewCell { }
class BlueCell: UITableViewCell { }
extension UITableView {
func dequeueReusableCell<T: UITableViewCell>(_ type: T.Type, for indexPath: IndexPath) -> T {
let identifier = String(describing: T.self) // Must set on Storyboard
return dequeueReusableCell(withIdentifier: identifier, for: indexPath) as! T
}
}
This makes dequeuing cells of the correct type very easy:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return tableView.dequeueReusableCell(RedCell.self, for: indexPath) // type: RedCell
}
Now, rather than typing RedCell.self
into that function call, I would like to store this SomeCell.self
on a variable so that each of the enum cases can pass their own custom cell subclass to the table view:
enum Color {
case red, blue
// ...?
// func cellType<T: UITableViewCell>() -> T.Type {
// func cellType<T>() -> T.Type where T: UITableViewCell {
func cellType<T>() -> T.Type {
switch self {
case .red: return RedCell.self // Cannot convert return expression of type 'RedCell.Type' to return type 'T.Type'
case .blue: return BlueCell.self // Cannot convert return expression of type 'BlueCell.Type' to return type 'T.Type'
}
}
}
Desired result is to construct the cell via the enum case:
let color = Color.red
let cell = tableView.dequeueReusableCell(color.cellType(), for: indexPath) // type: UITableViewCell
It's fine for the return type of the above call to be upcast to the in-common UITableViewCell
, rather than a subclass. But the cellType()
should dequeue the proper cell subclass from the Storyboard, as shown in the first code block, which is based on a String of the class name.
Is this possible? Xcode gives the errors above for my attempts to write the function.
What is the correct syntax for the generic function I'm attempting to write?
CodePudding user response:
No need for generics; just return UITableViewCell.Type
:
enum Color {
case red, blue
func cellType() -> UITableViewCell.Type {
switch self {
case .red: return RedCell.self
case .blue: return BlueCell.self
}
}
}
CodePudding user response:
Im not sure I'm a fan of the idea but have a look at this, just use a private static variable and set it the desired type.
This way you avoid the inferring error from the return statement, and still change the type according to your enum case.
enum Color {
private static var cellType = UITableViewCell.self
case red, blue
private func setCellType(){
switch self{
case .red:
Color.cellType = RedCell.self
case .blue:
Color.cellType = BlueCell.self
}
}
func cellType<T: UITableViewCell>() -> T.Type {
setCellType()
return Color.cellType as! T.Type
}
}
class Test {
init(){
print(String(describing: Color.red.cellType()))
}
}
let test = Test()