1

I have a window with an NSTableView that is populated from an NSMutableArray.

In one column I programmatically create an NSPopUpbutton and add the items and set the title according to a value in the data source array.

When the window is first drawn everything is perfect. If I use the search function or the table ever gets redrawn with [tableView reloadData] the buttons in the cell are all off and everything goes sideways.

Based on suggestions I modified the way I create the NSPopUpButton so that it isn't drawn over and over but I can't figure out why or how to stop it from getting all messed up.

I know cells are recycled but I'm lost as to how to ensure that the recycled cells are clean.

The important part of the code is below (there's a lot of other stuff but this is how I deal with the buttons)

In my header file:

@public
IBOutlet NSPopUpButton *button;

In my Implementation file I create the button as such:

- (void) awakeFromNib{
//Create popup button
button = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(2, 1, 200, 22) pullsDown:NO];
[button setBordered:YES];
[button setButtonType:NSMomentaryLightButton];
[button setBezelStyle:NSRoundedBezelStyle];
[button setHidden:YES];
[button setAction:@selector(selectedAction:)];
}

And then when the view is drawn:

- (NSView *)tableView:(NSTableView *)table_view viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
Proposal *p = [list objectAtIndex:row];
NSString *identifier = [tableColumn identifier];

NSTableCellView *cell = [table_view makeViewWithIdentifier:identifier owner:self];

if([identifier isEqualToString:@"status"]){
    cell.textField.stringValue = @"";

    if(p){
        //Check which button we need
        if ([p.status isEqualToString:@"Approved"]){
            [cell addSubview:button];
            [button addItemWithTitle:@"Pending"];
            [button addItemWithTitle:@"Completed"];
            [button addItemWithTitle:@"Rejected"];                
            [button setTitle:@"Approved"];
            [button setHidden:NO];
        }
    }
 }
 }

There's more to the code (more columns) but they aren't necessary to this so I omitted them so to be concise.

This code successfully draws the buttons and like I said everything is perfect on first draw but everything gets majorly messed up if the table ever has to reload data.

So I'm totally stumped. I've tried creating the button in IB but then I can't access it from the code to change the title or items... I've tried subclassing NSPopUpButton but I end up at the same place.

julian
  • 157
  • 1
  • 12
  • Also in macOS cells / views are reused. Since the table view is view based anyway it's more convenient to create a second (custom) cell view with popup button in the table view in Interface Builder and return the cells accordingly. – vadian Mar 01 '17 at 17:34
  • If I follow- you're suggesting creating the NSPopUpButton in IB and then controlling it programmatically? I have tried that but can't seem to affect any change on the button. Calls like `[button addItemWithTitle:@"Rejected"];` and `[button setTitle:@"Approved"];` don't seem to do anything. Could I be binding it incorrectly? – julian Mar 01 '17 at 17:45
  • No I mean a second separate `NSTableCellView` in Interface Builder. Drag the popup button into that second view and create the menu items. Create a custom Cocoa class file, name it for example `ButtonTableCellView`. Add an `IBOutlet` for the popup.button. Connect the button in Interface Builder. Set the class of the second table cell view to `ButtonTableCellView` and assign an identifier. In `cellForRow` if status is `Approved` return a `ButtonTableCellView` otherwise the standard `NSTableCellView`. The entire code in `awakeFromNib` and the code related to `button` is not needed. – vadian Mar 01 '17 at 17:51
  • Ok, I think I follow and have created everything ok, but am hung up on how to return the `ButtonTableCellView` – julian Mar 01 '17 at 18:27
  • Check first `identifier == "status"` then if `status == "Approved"` return `ButtonTableCellView *cell = (ButtonTableCellView *)[table_view makeViewWithIdentifier:"buttonCellIdentifier" owner:self];` otherwise the standard cell. `buttonCellIdentifier` is the identifier of the second view. – vadian Mar 01 '17 at 18:33
  • Does the NSTableCellView have to be placed in the column or can it just be dropped into the Xib anywhere...? Thanks for all the hand holding, this is uncharted waters for me. Is there some code somewhere that I can see? – julian Mar 01 '17 at 18:51
  • Design the cell directly in the table view (column) in the xib. You can create as much different cells / views as you want. Watch the WWDC video about view based table views (from 2011 or 2012). – vadian Mar 01 '17 at 19:01

0 Answers0