NSTableView setObjectValue not called

My application presents a list of words to the user, who will then select a number of them. They may also edit the words in the table. The table is a single column, cell-based table.


The application is very small, so the app delegate is being used as the NSTableViewDataSource and NSTableViewDelegate. The data source is working correctly, as the right words are appearing in the table. I am able to get a list of selected words from the table after the user presses the Done button.


The part that is missing is getting edits of words in the table. I have added the - (void)tableView:setObjectValue:forTableColumn:row: method, right next to the methods for populating the table. I put a call to NSLog in the method, but the method is not being called- nothing appears in the console.

What might prevent the method from being called? Exactly what user actions will trigger the sending of the message to the table data source?

Thanks

Andrew

I think you've implemented the wrong method. Right above the setObjectValue method in the NSTableView.h header is this one:


- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row;


Replace the method header with this one and tweak the code to just return the object value, and everything should work just fine.



Cell-based table views have been deprecated since 10.10 Yosemite, so, unless you're targeting Snow Leopard or earlier, I'd recommend that you make the simple move to a view-based table view, which is far more flexible, capable, and easy to use.

Ok I threw together a quick and dirty app to test the normal mechanism and it works fine

The app delegate, which again is also the table delegate and data source, looks like this


@interface AppDelegate () <NSTableViewDataSource, NSTableViewDelegate>
    @property (weak) IBOutlet NSWindow *window;
    @property (nonatomic, strong) NSArray *data;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

  self.data = @[[@{@"name":@"Jonathan"} mutableCopy], [@{@"name":@"Richard"} mutableCopy]];
  [self.window makeKeyAndOrderFront:nil];

}

- (void)applicationWillTerminate:(NSNotification *)notification
{
  NSLog(@"%@", self.data.description);
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
  return 2;
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
  return [[self.data objectAtIndex:row] valueForKey:tableColumn.identifier];
}

- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
  [[self.data objectAtIndex:row] setValue:object forKey:tableColumn.identifier];
}
@end


All you have to do is make sure the table column is editable (in interface builder) and has the correct identifier which here would be "name" and everything works. The - (void)tableView:setObjectValue:forTableColumn:row: gets called as expected and sets the value.

Wait a minute—I just realized that my last post was incorrect! 😟 I haven't worked with cell-based table views in years (they have been officially deprecated since last year), so I forgot that the two methods in question (objectValue… and setObjectValue…) did different jobs. Sorry if I confused you!

Thanks. It looks like the column not having an identifier set was where I went wrong.


However, I also found another way to get the edited values from the table.


  // this bit goes in applicationDidFinishLaunching
  [[NSNotificationCenter defaultCenter] addObserver:self
                      selector:@selector(editingDidEnd:)
                      name:NSControlTextDidEndEditingNotification
                        object:nil];

// this notification is sent by the table cell field editor
- (void)editingDidEnd:(NSNotification *)notification
{
  NSControl *control = [notification object];
  NSView *cellView = [control superview];
  NSInteger tableRow = [keyTable rowForView:cellView];
  NSString *cellText = [control stringValue];
  [keysList replaceObjectAtIndex:tableRow withObject:cellText];
}


I got this from Technical Q&A QA1551. The table cell's field editor sends the notification when the user finishes editing (tabs out, clicks elsewhere, hits return).

NSTableView setObjectValue not called
 
 
Q