0

I'm running into a simple problem but have yet to find an optimal solution. I have a view based NSTableView that is loading it's cell views from different xibs. My table view is dynamic and based on user input I will dynamically add and remove rows ultimately adjusting the table data source. Each one of my NSTableCellViews have a button in it and I link the IBAction click handler to the NSView that holds the table view. What I need to do is get the row number for the button that was clicked in the table view so I can process the logic. I am able to do this successfully in : tableViewSelectionDidChange:(NSNotification *)notification

Here is how I do it:

- (void)tableViewSelectionDidChange:(NSNotification *)notification {
    NSTableView *tableView = [notification object];
    NSInteger selectedRow = [tableView selectedRow];
}

This works perfectly for a user actually clicking the row. Now when I move the NSButton IBAction and link it in the NSView as follows:

- (IBAction)buttonClickHandler:(NSButton *)sender {
    NSInteger selectedRow = [self.tblView rowForView:sender];
    NSLog(@"%ld", (long)selectedRow);
}

I based this approach from this selected answer.

I also tried this:

- (IBAction)buttonClickHandler:(NSButton *)sender {

    id representedObject = [(NSTableCellView *)[sender superview] objectValue];
    NSLog(@"%@", representedObject);
}

//My configuration 

- (void)configureView {

    [self.view setFrame:[self bounds]];
    [self addSubview:self.view];

    [self.view setWantsLayer:YES];

    [self.view setTranslatesAutoresizingMaskIntoConstraints:NO];

    self.tblView.delegate = self;
    self.tblView.dataSource = self;





    [self.tblView setIntercellSpacing:NSMakeSize(0, 0)];

    [self.tblView registerNib: [[NSNib alloc] initWithNibNamed:@"ParentCellXib" bundle:nil] forIdentifier:@"ParentCell"];
    [self.tblView registerNib: [[NSNib alloc] initWithNibNamed:@"ChildCellXib" bundle:nil] forIdentifier:@"ChildCell"];
    [self.tblView registerNib: [[NSNib alloc] initWithNibNamed:@"HeaderCellXib" bundle:nil] forIdentifier:@"HeaderCell"];
}

But the represented object returns null. If it's worth mentioning, I've set my File's Owner as the View that holds the tableView so I can link the IBAction and I've subclassed the TableCellView to a different class. However, I don't think this is part of the problem as far as I can see. Is there a simple solution to reliably give me the selectedRow number based on a button click in that cell? Both approaches I tried above return -1 and null respectively.

Community
  • 1
  • 1
zic10
  • 2,310
  • 5
  • 30
  • 55
  • 1
    So where and what doesn't work? You say what works but don't say what doesn't work. – rocky Apr 05 '16 at 00:32
  • I updated the post for further clarification on what the problem is. – zic10 Apr 05 '16 at 00:37
  • `rowForView` should work. Is `self.tblView` correct and is `sender` a subview of `self.tblView`? Is the NSView the delegate of `self.tblView`? Objects inside view based table views may only be connected to the table view's delegate. – Willeke Apr 05 '16 at 13:35
  • The tblView is a subView of the view but the xibs are loaded programatically. The xibs are table cell views. and the button is on the xibs themselves. I suspect this might have something to do with it. I'll update more of the code to show the context. – zic10 Apr 05 '16 at 13:37

3 Answers3

0

I would set the row in NSButton's tag property:

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    SomeTableCellView *cell = [tableView makeViewWithIdentifier:@"cell" owner:self];
    if (cell == nil) {
        cell = // init some table cell view
        cell.identifier = @"cell";
    }

    cell.button.tag = row;
    [cell.button setTarget:self];
    [cell.button setAction:@selector(buttonAction:)];
}

- (IBAction)buttonAction:(id)sender {
    NSLog(@"row: %d", sender.tag);
}
rocky
  • 3,521
  • 1
  • 23
  • 31
0

Try This

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    yourCustomeCell *aCell;
    NSString *aStrIdentifier = @"yourIdentiFier";
    aCell = (yourCustomeCell *)[tableView dequeueReusableCellWithIdentifier:aStrIdentifier];

    //you have to set your indexpath
    objc_setAssociatedObject(aCell.btnUpload_or_Add, @"objBtn", indexPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [aCell.YourButton addTarget:self action:@selector(yourButtonActiontapped:) forControlEvents:UIControlEventTouchUpInside];

    return aCell;
}

-(IBAction)yourButtonActiontapped:(UIButton *)sender{

    NSIndexPath *aIndPath =  objc_getAssociatedObject(sender, @"objBtn");
    NSLog(@"row:%@",aIndPath.row);
}

also you have to import #import <objc/runtime.h>

another way to get row in IBAction is TAG but objc is better option insted of TAG.

Vvk
  • 4,031
  • 29
  • 51
0

Create a subclass of UIButton and add a property for NSIndexPath for the button. Use this button in cellForRowAtIndexPath method. assign the index path of the cell to that of index path of the button.

On Tap, get the index path from its sender. In your case index path of that button.

Abdul Yasin
  • 3,480
  • 1
  • 28
  • 42