3
votes

I have a view with a view-based NSTableView (which itself has a cell view with a single text field) and some buttons and textfields outside the tableview. One of the buttons adds an object into the datasource for the tableview, and after inserting the row into the tableview, immediately makes it editable.

If the user enters the text and pressed the return key, I receive the - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor delegate method fine, and I can run my validation and save the value. But the delegate doesn't get called if the user selects any of the other buttons or textfields outside the tableview.

What's the best way to detect this loss-of-focus on the textfield inside the NSTableCellView, so I can run some of my validation code on the tableview entry?

1

1 Answers

2
votes

If I understand you correctly you want a control:textShouldEndEditing: notification to fire in the following situation:

  1. You add a new object to the array controller.
  2. The row in the table representing the object is automatically selected.
  3. YOU programmatically select the text field in the relevant row for editing.
  4. The user immediately (i.e. without making any edits in the text field) gives focus to a control elsewhere in the UI

One approach I've used in the past to get this working is to make an insignificant programmatic change to the field editor associated with the text field, just before the text field becomes available to the user for editing. The snippet below shows how to do this - this is step 2/step 3 in the above scenario:

func tableViewSelectionDidChange(notification: NSNotification) {
    if justAddedToArrayController == true {
        // This change of selection is occurring because the user has added a new
        // object to the array controller, and it has been automatically selected 
        // in the table view. Now need to give focus to the text field in the 
        // newly selected row...

        // Access the cell
        var cell = tableView.viewAtColumn(0,
            row: arrayController.selectionIndex,
            makeIfNecessary: true) as NSTableCellView

        // Make the text field associated with the cell the first responder (i.e. 
        // give it focus)
        window.makeFirstResponder(cell.textField!)

        // Access, then 'nudge' the field editor - make it think it's already
        // been edited so that it'll fire 'should' messages even if the user 
        // doesn't add anything to the text field
        var fe = tableView.window?.fieldEditor(true, forObject: cell.textField!)
        fe!.insertText(cell.textField!.stringValue)
    }
}