Reputation: 1142
So I was wondering about whether I could save a type in a variable, to be used later on in the same function.
My code is as follows:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let object = array.item(at: indexPath.row) else {
fatalError("Could not retrieve the table object")
}
if object.displayOnLeft {
guard let cell = tableView.dequeueReusableCell(withIdentifier: LeftSidedCell.className, for: indexPath) as? LeftSidedCell else {
fatalError("Could not dequeue the left sided cell")
}
cell.object = object
return cell
} else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: RightSidedCell.className, for: indexPath) as? RightSidedCell else {
fatalError("Could not dequeue the right sided cell")
}
cell.object = object
return cell
}
}
But I figured that this is actually quite clunky, since the contents inside the if and the else are essentially the same, with just the type of cell differing.
I ideally want an algorithm that is basically:
var type
if object.displayOnLeft {
type = LeftSidedCell
} else {
type = RightSidedCell
}
//Dequeue Cell with type
I understand there are a few issues here, firstly, I cannot declare a variable without a type, and i'm not sure what type to assign it to at first. Second, retrieving the type of class has not been fruitful either.
I have tried storing it as a property in the Object, as well as returning it in a function such as this in my custom object as well as some variations of the following:
func getTypeOfCell<T:TranslationCellProtocol>() -> T.Type {
if displayOnLeft {
return LeftSidedCell.self
} else {
return RightSidedCell.self
}
}
Anyway, I'm not sure if this is possible or if i have a fundamental misunderstanding of a concept, but any help would be much appreciated.
Thank you.
Upvotes: 3
Views: 117
Reputation: 535232
As long as LeftSidedCell and RightSidedCell have a common superclass — say, MySidedCell — you can store them in a variable of type MySidedCell.Type
:
let cellType : MySidedCell.Type = LeftSidedCell.self
You can later just test that value with ==
to see which cell type it is.
if cellType == LeftSidedCell.self {
Upvotes: 2
Reputation: 4659
To mind mind you are clogging your code with so many optional checks and those fataError
calls. By the time cellForRow
is called you should already be sure that your datasource is correct. So there is no need to optionally unwrap your data and table view cells at this point as the app will crash anyway if the data are incorrect.
E.g. do a check if your array has no items or items are somehow invalid before numberOfRowsInSection
is called, if your data is not correct return 0 number of items and cellForRow
will not get called with that faulty data.
Regarding code cleaniness, this would do for me:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let object = array[indexPath.row]
let cell: UITableViewCell
if object.displayOnLeft {
cell = tableView.dequeueReusableCell(withIdentifier: "LeftSidedCellIdentifier", for: indexPath) as! LeftSidedCell
} else {
cell = tableView.dequeueReusableCell(withIdentifier: "RightSidedCellIdentifier", for: indexPath) as! RightSidedCell
}
cell.object = object
return cell
}
Upvotes: 1
Reputation: 6982
First, write a protocol that implements className()
method (or any methods and properties you will use for both cell classes) and have both your cell classes conform to it
protocol YourCellProtocol {
var object : YourObjectClass? { get set }
static func className() -> String
}
class LeftSidedCell : YourCellProtocol {...)
class RightSidedCell : YourCellProtocol {...}
Then you will be able to do something like that
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let object = array.item(at: indexPath.row) else {
fatalError("Could not retrieve the table object")
}
var type : YourCellProtocol.Type
if object.displayOnLeft {
type = LeftSidedCell.self
} else {
type = RightSidedCell.self
}
let cell = tableView.dequeueReusableCell(withIdentifier: type.className, for: indexPath)
if let yourCell = cell as? YourCellProtocol
{
yourCell.object = object
}
return cell
}
Upvotes: 2