I am trying to set a property called activeTableViewCell
declared as;
var activeTableViewCell: UITableViewCell?
using a switch statement in my cellForRowAt
delegate method which sets the property to one of two possible values depending upon another property called deviceOrientation
;
switch deviceOrientation {
case .portrait:
activeTableViewCell = tableView.dequeueReusableCell(withIdentifier: "CompanyStockCell", for: indexPath) as! CompanyStockCellPortrait
case .landscape:
activeTableViewCell = tableView.dequeueReusableCell(withIdentifier: "CompanyStockCell", for: indexPath) as! CompanyStockCellLandscape
}
but Xcode reports an error on the next line of code;
activeTableViewCell.symbolValue.text = companyStockInfo[indexPath.row].symbol
with the error message;
Value of type ‘UITableViewCell?’ has no member named ‘symbolValue’
symbolValue
is a stored property of CompanyStockCellPortrait
and CompanyStockCellLandscape
both of which are subclasses of UITableViewCell
.
How can I get this to work?
2
Answers
You can use a base class to hold to common properties, and derive the two other classes from it:
If these two classes exist solely to support a different layout, but are otherwise identical, I would recommend consolidating into a single class.
For example, if you want to have different layouts for device orientations, then implement unique constraints contingent upon the appropriate orientation using size classes.
Consider my example below, where each table row has two subviews, a red one and a blue one. Let us assume that in landscape orientation, there is room to see one next to the other, but in portrait orientation, you have to put the second one below the first. You can handle this all with a single cell class, but just customize which constraints are employed in each device orientation (i.e., each horizontal size class).
In this scenario, let us consider just one particular constraint, the “should the tops of the two views be aligned.” In the highlighted part of the Xcode screen snapshot, I show that the constraint is not installed in a horizontal compact size class (i.e., portrait), but is in regular size class (i.e., landscape):
You can just repeat that process for each of the constraints that vary by size class.
This has several advantages:
You then end up with a single cell class. It is less code, less duplicative code, and completely eliminates your question of how to reference the same property in two different classes;
Enjoy a unique layout for each size class (i.e., orientation); and
The animation is more elegant, not requiring a redraw of the whole view, but animates the views into the right places, without having to reload the table view on rotation events:
If you cannot do this for some reason, you have a few other alternatives:
I think the single cell class with custom size class constraints is the best, but if your two cells have significantly different code implementations, too, then you can fall back to one of these other two, older, patterns.
I must confess that this size class approach takes a few tries to get comfortable with it, so you might experiment with some simple examples before you attempt refactoring your existing codebase.