How to create an action from selecting a row from an NSTableView

家住魔仙堡 提交于 2019-12-03 22:56:51
Coderama

So the issue here was that I was trying to use the tableViewSelectionChange to trigger an event when a row in the NSTableColumn was clicked. As I couldn't get this working I took another approach which was to create an IBAction and link this to the NSTableView and I have found this to work well.

In order to do this, I did the following:

  1. Delete - (void)tableViewSelectionDidChange
  2. Create IBAction
  3. In the XIB file, create a Received Actions link between the IBAction and the NSTableView, in NSTableView connection inspector under "sent action" have "selector" action" connect this "selector" with that IBAction you want to trigger.

This is the IBAction in PersonController.m

- (IBAction)columnChangeSelected:(id)sender
{
    NSInteger selectedRow = [personsTable selectedRow];

    if (selectedRow != -1) {
        NSLog(@"Do something with selectedRow!");
    }
    else {
        // No row was selected
    }
}

To expand on Coderama's answer, the equivalent in code is:

tableView.target = self;
tableView.action = @selector(tableViewClicked:);

then implement the method in the same class:

- (void)tableViewClicked:(id)sender {
    // This will return -1 if the click did not land on a row
    NSLog(@"tableView.clickedRow = %ld", tableView.clickedRow);

    // This will return -1 if there is no row selected.
    NSLog(@"tableView.selectedRow = %ld", tableView.selectedRow);
}

The table view will call its action method on the target you set every time the view is clicked. This will allow you to know every time a row is selected, even if it is already selected.

Make sure that the instance of PersonController is connected to personsTable as the delegate. I don't know how you created the NSTableView, but if your are using Nibs, you can set the delegate in Interface Builder. If not, you can add [personsTable setDelgate:self] in the init method and [personsTable setDelegate:nil] in the dealloc method.

Also, you are leaking personsList. Add [personsList release] to your delegate method.

For others who bump into this issue: other reason for this delegate not being called could be because the row is already selected. So it wont notify unless a new selection is made. If you still want to be able to receive notifications on every click deselect all rows once you get notified.

Now this will make 2 calls to your delegate, one for getting selected and other for getting deselected. Second call is not needed so add a condition on top to check the [tableView selectedRow] this would return -1 when no rows are selected.

Solution in Swift 3 for most of the events:

Inside tableview view controller :

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.target = self
    tableView.action = #selector(tableViewDidClick)
}

func tableViewDidClick(){
    let row = tableView.clickedRow
    let column = tableView.clickedColumn
    let unselected = -1

    if row == unselected && column == unselected{
        tableViewDidDeselectRow()
        return
    }else if row != unselected && column != unselected{
        tableViewDidSelectRow(row)
        return
    }else if column != unselected && row == unselected{
        tableviewDidSelectHeader(column)
    }
}

private func tableViewDidDeselectRow() {
    // clicked outside row
}

private func tableViewDidSelectRow(_ row : Int){
    // row did select
}

private func tableviewDidSelectHeader(_ column : Int){
    // header did select
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!