Move focus to newly added record in an NSTableView
Asked Answered
T

3

13

I am writing an application using Core Data to control a few NSTableViews. I have an add button that makes a new a record in the NSTableView. How do I make the focus move to the new record when this button is clicked so that I can immediately type its name? This is the same idea in iTunes where immediately after clicking the add playlist button the keyboard focus is moved to the new line so you can type the playlist's name.

Turner answered 10/5, 2009 at 8:27 Comment(2)
How is your data stored? In an array controller?Indent
Yes it's in an NSArrayController.Turner
I
19

Okay well first of all, if you haven't already got one, you need to create a controller class for your application. Add an outlet for the NSArrayController that your objects are stored in, and an outlet for the NSTableView that displays your objects, in the interface of your controller class.

IBOutlet NSArrayController *arrayController;
IBOutlet NSTableView *tableView;

Connect these outlets to the NSArrayController and the NSTableView in IB. Then you need to create an IBAction method that is called when your "Add" button is pressed; call it addButtonPressed: or something similar, declaring it in your controller class interface:

- (IBAction)addButtonPressed:(id)sender;

and also making it the target of your "Add" button in IB.

Now you need to implement this action in your controller class's implementation; this code assumes that the objects you have added to your array controller are NSStrings; if they are not, then replace the type of the new variable to whatever object type you are adding.

//Code is an adaptation of an excerpt from "Cocoa Programming for
//Mac OS X" by Aaron Hillegass
- (IBAction)addButtonPressed:(id)sender
{
//Try to end any editing that is taking place in the table view
NSWindow *w = [tableView window];
BOOL endEdit = [w makeFirstResponder:w];
if(!endEdit)
  return;

//Create a new object to add to your NSTableView; replace NSString with
//whatever type the objects in your array controller are
NSString *new = [arrayController newObject];

//Add the object to your array controller
[arrayController addObject:new];
[new release];

//Rearrange the objects if there is a sort on any of the columns
[arrayController rearrangeObjects];

//Retrieve an array of the objects in your array controller and calculate
//which row your new object is in
NSArray *array = [arrayController arrangedObjects];
NSUInteger row = [array indexOfObjectIdenticalTo:new];

//Begin editing of the cell containing the new object
[tableView editColumn:0 row:row withEvent:nil select:YES];
}

This will then be called when you click the "Add" button, and the cell in the first column of the new row will start to be edited.

Indent answered 10/5, 2009 at 10:8 Comment(1)
NSArrayController has IBAction "add". You can link a button to this action. Can you call it directly? (I tried it, doesn't work) If you could, you would have to create a new object like this, but just call add, right?Swain
D
1

I believe an easier and more proper way to do it is by implementing it this way.

-(void)tableViewSelectionDidChange:(NSNotification *)notification {
    NSLog(@"%s",__PRETTY_FUNCTION__);
    NSTableView *tableView = [notification object];
    NSInteger selectedRowIndex = [tableView selectedRow];
    NSLog(@"%ld selected row", selectedRowIndex);

    [tableView editColumn:0 row:selectedRowIndex withEvent:nil select:YES];

I.e.

  1. Implement tableViewSelectionDidChange:(NSNotification *)notification
  2. fetch the selected row index
  3. Call editColumn:(NSInteger)column row:(NSInteger)row withEvent:(NSEvent *)theEvent select:(BOOL)select from there with the row index.

Important note: this solution will also trigger the editing when user will simply select a row. If you only want editing triggered when adding a new object, this is not for you.

Doroteya answered 8/10, 2014 at 17:40 Comment(0)
Y
1

Just create a separate @IBAction in your controller and invoke the NSArrayController.add method manually. After that you can select the row

@IBAction func addLink(_ sender: Any) {
    // Get the current row count from your data source
    let row = links.count

    arrayController.add(sender)

    DispatchQueue.main.async {
        self.tableView.editColumn(0, row: row, with: nil, select: true)
    }
}
Yeeyegg answered 4/1, 2019 at 20:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.