Delegate events for NSTextField in a view-based NS

2019-04-10 19:45发布

问题:

I have a flawless functioning view-based NSOutlineView with a proper set-up datasource in my project. Now I want to allow the user to change certain entries. So I made the NSTextField in the IB editable. For a cell-based NSOutlineView you can use the delegate method outlineView:setObjectValue:forTableColumn:byItem: however it's not available for a view-based NSOutlineView as stated in the header file for the NSOutlineViewData protocol:

/* View Based OutlineView: This method is not applicable. */

(void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;

So I searched for another delegate method and found outlineView:shouldEditTableColumn:item:. However this delegate method doesn't get fired. Probably because I'm not editing a cell.

So my question is: Is there any other way to notice when a row changed than having a delegate for each NSTextField?

回答1:

You are correct that your text field needs to be editable in Interface Builder.

Next, make your controller conform to NSTextFieldDelegate. Then, set the delegate for the text field in outlineView:viewForTableColumn:item:, like so:

tableCellView.textField.delegate = self

Here's a simplified example, where you've implemented the method for returning the table cell view for an item for your outline view.

-(NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
    NSTableCellView *tableCellView = [outlineView makeViewWithIdentifier:@"myTableCellView" owner:self];

    MyItem *myItem = (MyItem *)item; // MyItem is just a pretend custom model object 
    tableCellView.delegate = self;
    tableCellView.textField.stringValue = [myItem title];

    tableCellView.textField.delegate = self;

    return result;
}

Then, the controller should get a controlTextDidEndEditing notification:

- (void)controlTextDidEndEditing:(NSNotification *)obj
{
    NSTextField *textField = [obj object];
    NSString *newTitle = [textField stringValue];

    NSUInteger row = [self.sidebarOutlineView rowForView:textField];

    MyItem *myItem = [self.sidebarOutlineView itemAtRow:row];
    myItem.name = newTitle;  
}


回答2:

Well, it seems like Apple wants us to use the delegate methods of each NSTextField as stated here:

This method is intended for use with cell-based table views, it must not be used with view-based table views. Instead target/action is used for each item in the view cell.

So there's currently no other way to do this.