Runt8
Runt8

Reputation: 611

View-based NSTableView From Xib

I have a NSTableView that is created programmatically. I have several options for customizing the cells in each column based on the column type and datasource (ie, it's very easy to have buttons or checkboxes based on the column type and what is in the datasource).

Now I need to be able to fully customize the cell, so I'm attempting to load an NSView from a xib and return it from the tables delegate's viewForTableColumn method. I haven't used IB much outside of iOS and I'm not very well versed as to how the various outlets and class types should be set, especially when the majority of the UI is created outside of IB. I've read many posts here and on other sites but the majority of examples either create all of the UI in IB or none of it.

Currently I have TestCell.xib which was created by selecting View from the New File dialog. I've also created an objective-c class called TestCell. In IB I've set the view's class to TestCell, and I've dragged outlets for a label control and a button to the TestCell class.

In the table's delegate class I have the following:

- (NSView*)tableView:(NSTableView*)tableView viewForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row {
    NSView* view = [tableView makeViewWithIdentifier:customRowXibName owner:self];
    if( view == nil ) {
        NSArray* nibObjects = nil;
        if( [[NSBundle mainBundle] loadNibNamed:customRowXibName owner:self topLevelObjects:&nibObjects] ) {
            view = [nibObjects lastObject];
        }
    }

    return view;
}

However, the table view doesn't show anything. I'm also getting the following errors for both controls in the view when loading the xib:

Failed to connect (button) outlet from (TableListViewDelegate) to (NSButton): missing setter or instance variable

I'm assuming that's because I'm setting owner to self when loading the xib.

My questions are:

  1. In IB, what should the File's Owner placeholder be set to? Currently it's set to TestCell but I don't believe that is correct.
  2. Is it ok to use "TestCell" as the identifier? Does this identifier need to be set in IB? Or do I need to call registerNib:forIdentifier on the table view?
  3. When calling loadNibNamed, what should owner be set to?

Upvotes: 1

Views: 461

Answers (1)

Runt8
Runt8

Reputation: 611

I was able to get this to work by doing the following:

  1. In IB, set the File's Owner to be the class that is loading the Xib (in this case, the NSTableViewDelegate).
  2. In the delegate, create an outlet for your custom cell and hook it up in IB (I used the Connection Inspector with the File's Owner selected).
  3. In tableView:viewForTableColumn:row call:[tableView makeViewWithIdentifier:@"Xib Name" owner:self]

  4. If that returns nil, then call:[[NSBundle mainBundle] loadNibNamed:@"Xib Name" owner:self topLevelObjects:&nibObjects] with nibObjects being a nil NSArray*.

  5. If loadNibNamed returns YES, then the outlet you created in the delegate should now point to the newly loaded view. Make sure to set the views identifier to @"Xib Name" so you can make use of cached views.

Upvotes: 1

Related Questions