jdmoser
jdmoser

Reputation: 23

Updating datasource on NSTableView cell edit

I've been struggling with this for three days. I've looked up everything I can find on here and on Google, so please understand that I ask this after already exhausting myself trying to find the answer. I'm also new to Cocoa, so I apologize if this appears to be trivial, but it isn't to me. I'm learning! :)

I'm populating an NSTableView with simple string values. That's all I need. I also need those values to be editable inline. So far so good, I've gotten all of that working.

The problem is that I can't figure out how to save those changes to my datasource. I've tried all the suggested delegate methods and they either don't get called, or I can't figure out how to get the updated value to assign to my NSMutableArray.

Here's the code:

//
//  AppDelegate.m
//  TableView
//

//  Created by Jay Moser on 2016-03-07.
//  Copyright © 2016 Jay Moser. All rights reserved.
//

#import "AppDelegate.h"

@interface AppDelegate ()

@property (weak) IBOutlet NSWindow *window;
@end

@implementation AppDelegate
{
    NSMutableArray* _tableContents;
    IBOutlet NSTableView* _tableView;
}

- (IBAction)Add:(id)sender
{
    [_tableView reloadData];
}

- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
    _tableContents = [[NSMutableArray alloc] init];

    [_tableContents addObject:@"Item 1"];
    [_tableContents addObject:@"Item 2"];
    [_tableContents addObject:@"Item 3"];
    [_tableContents addObject:@"Item 4"];
    [_tableContents addObject:@"Item 5"];
    [_tableContents addObject:@"Item 6"];
    [_tableContents addObject:@"Item 7"];
    [_tableContents addObject:@"Item 8"];

    [_tableView reloadData];
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
    return [_tableContents count];
}

- (NSView*)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    NSTableCellView* cellView = [_tableView makeViewWithIdentifier:@"name" owner:self];
    cellView.textField.stringValue = _tableContents[row];

    return cellView;
}

// ====================================================================================
//
//  If I run the application, double click an item in the tableview and, for example,
//  rename "Item 4" to "Renamed Item" ... I need a method here to detect that the change
//  happened and changes "Item 4" in _tableContents to "Renamed Item"
//
//
// ====================================================================================

@end

Upvotes: 2

Views: 955

Answers (1)

Borys Verebskyi
Borys Verebskyi

Reputation: 4268

You need to specify target and action for text field, that will be called when your cell will finish editing:

- (NSView*)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    NSTableCellView* cellView = [_tableView makeViewWithIdentifier:@"name" owner:self];
    cellView.textField.stringValue = _tableContents[row];
    [cellView.textField setTarget:self];
    [cellView.textField setAction:@selector(onEditRow:)];
    return cellView;
}

- (IBAction)onEditRow:(id)sender
{
    NSInteger row = [_tableView rowForView:sender];
    if (row != -1) {
        _tableContents[row] = [sender stringValue];
    }
}

See this answer regarding alternate way to setup action using interface builder.

Upvotes: 2

Related Questions