skip to Main Content

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


  1. You can use a base class to hold to common properties, and derive the two other classes from it:

    class CompanyStockCell: UITableViewCell {
        var symbolValue: UILabel
        // other common stuff
    }
    
    class CompanyStockCellPortrait: CompanyStockCell {
       // specific portrait stuff
    }
    
    class CompanyStockCellLandscape: CompanyStockCell {
       // specific landscape stuff
    }
    
    Login or Signup to reply.
  2. 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):

    enter image description here

    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:

      enter image description here


    If you cannot do this for some reason, you have a few other alternatives:

    • have a single cell class, two different NIBs or storyboard prototype cells that use this same cell class for both; or
    • have the two cell classes, but a protocol to define the common property between two classes.

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search