Reusing table view cells in a Mac application

1.2k views Asked by At

I am currently trying to convert my iOS application onto the Mac and therefore I would like to replicate some of the behaviours from the iOS version. In the mobile application I use dynamic table view rows with regards to content and height and when I set the data that has to be displayed, I adjust the frame of the views that are contained by the cell.

For example:

I initiate a cell with a height of 100, then, for another cell, I reset the custom height property to, say 60, change the data object represented by the cell, and adjust its contained views so that they fit to that adjusted height.

However, on the Mac it does not seem to work quite as expected. The initialisation of the cells seems to work fine, but as soon as cells get reused, everything seems to get out of hand.

Here is my code:

- (NSView *)tableView:(NSTableView *)tableView
   viewForTableColumn:(NSTableColumn *)tableColumn
                  row:(NSInteger)row {


    // Get an existing cell with the 'View' identifier if it exists
    MyCustomTableCellView *result = [tableView makeViewWithIdentifier:@"View" owner:self];

    // There is no existing cell to reuse so create a new one
    if (result == nil) {

        float height = [[rowHeights objectAtIndex:row] floatValue];
        result = [[MyCustomTableCellView alloc] initWithFrame:NSMakeRect(0, 0, self.frame.size.width, height) height:height];

        // This allows the cell to be reused.
        result.identifier = @"View";
    }

    // result is now guaranteed to be valid, either as a reused cell
    result.height = [[rowHeights objectAtIndex:row] floatValue];
    result.data = [arrayToDisplay objectAtIndex:row];

    // Return the result
    return result;

}

and the setter of MyCustomTableCellView's data property:

-(void)setData:(Data *)d{

    data = d;

    titleLabel.stringValue = d.titleText;
    someLabel.stringValue = d.someText;

    float h = self.height-kInset;
    someLabel.frame = NSMakeRect(someLabel.frame.origin.x, titleLabel.frame.origin.y-h-10, self.bounds.size.width-130, h);

} 

As you can see, someLabel's text (in my case) is variably changing and I want it to adjust to the cell's dimensions. I can confirm that this happens ONLY WHEN A CELL IS REUSED.

Initialisation result:

+-------------------------------+
|titleLabel                     |
+-------------------------------+
|                               |
|someLabel                      |
|                               |
+-------------------------------+

Reuse result:

+-------------------------------+
|titleLabel                     |
+-------------------------------+
|                               | <---- UNWANTED OFFSET!
+-------------------------------+
|                               |
|someLabel                      |
|                               |
+-------------------------------+
1

There are 1 answers

0
the_critic On BEST ANSWER

Okay, for all those who come across the same problem:

Along with setting the new data in this piece of code:

- (NSView *)tableView:(NSTableView *)tableView
   viewForTableColumn:(NSTableColumn *)tableColumn
                  row:(NSInteger)row {


    // Get an existing cell with the 'View' identifier if it exists
    MyCustomTableCellView *result = [tableView makeViewWithIdentifier:@"View" owner:self];
    float height = [[rowHeights objectAtIndex:row] floatValue];
    // There is no existing cell to reuse so create a new one
    if (result == nil) {

        result = [[MyCustomTableCellView alloc] initWithFrame:NSMakeRect(0, 0, self.frame.size.width, height) height:height];

        // This allows the cell to be reused.
        result.identifier = @"View";
    }

    NSRect frame = result.frame;
    frame.size.height = height;
    result.frame = frame;
    // result is now guaranteed to be valid, either as a reused cell
    result.height = height;
    result.data = [arrayToDisplay objectAtIndex:row];

    // Return the result
    return result;

}

I also had to make sure to change the frame height of the cell (for whatever reason). So I basically also set the frame height of the cell to my dynamic height.