1

I have a UITableView. There is a button in the right side on each row. Now the problem is any button i tap, it returns me the value of indexPath.row is 0. But when i tap a button it should return me the corresponding value of indexPath.row. I am working in iOS 7. Where is the mistake i am doing?

Here is the code for creating buttons on cell:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

NSInteger index = [indexPath row];

UISegmentedControl  *renameButton = nil;

if (cell == nil) {

cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

    renameButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@"Rename"]];
    [renameButton setTag:6];
    [renameButton addTarget:self action:@selector(renameButtonClicked:) forControlEvents:UIControlEventValueChanged];
    [renameButton setSegmentedControlStyle:UISegmentedControlStyleBar];
    [renameButton setMomentary:YES];
    [renameButton setTintColor:[UIColor lightGrayColor]];
    [cell.contentView addSubview:renameButton];
    [renameButton release];

return cell;

Here is the code for the selector method:

- (void)renameButtonClicked:(id)sender {

isInEditMode = !isInEditMode;
[self setToolbarUserInterface];
[self setTableViewUserInterface];

while ([selectedItems count] > 0) {
    [selectedItems removeLastObject];
}

UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];
int index = [[self.tableView indexPathForCell:cell] row];

NSLog(@"Index value : %d",index);

NSString *newPath = [path stringByAppendingPathComponent:[items objectAtIndex:index]];

TextInputViewController *textInput = [[TextInputViewController alloc] init];
[textInput setPath:newPath Parent:parent andType:5];
[self.navigationController pushViewController:textInput animated:YES];
}
John
  • 163
  • 2
  • 3
  • 10
  • See [this answer](http://stackoverflow.com/a/5690329/457406) on how to get the indexPath of the cell in a way that won't break if Apples decides to change the view hierarchy again. That's why your code does not work, your code is fine on iOS6, but with iOS7 apple introduced a scrollview between the cell and its contentView. – Matthias Bauch Jan 31 '14 at 12:45

4 Answers4

0

You don't get UITableViewCell by calling:

UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];

Try add one more superview to access the cell:

UITableViewCell *cell = (UITableViewCell *)[[[button superview] superview] superview];

The structure the button layout on the table view is:

UITableViewCellContentView - [sender superview]
UITableViewCellScrollView - [[sender superview] superview]
UITableViewCell - [[[sender superview] superview] superview]

Hope this help

Greg
  • 25,317
  • 6
  • 53
  • 62
  • Be prepared to change the number of `superview` calls for iOS8 again. ;-) **Seriously, do not use code that depends on the view hierarchy of views from other frameworks**. – Matthias Bauch Jan 31 '14 at 12:41
  • @MatthiasBauch I haven't said that this is a good way of doing that.The question was about the error in this example and I just pointed what caused this error. – Greg Jan 31 '14 at 13:08
0

Use associated objects. This should work:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

NSInteger index = [indexPath row];

UISegmentedControl  *renameButton = nil;

if (cell == nil) {

cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

    renameButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@"Rename"]];
    [renameButton setTag:6];
    [renameButton addTarget:self action:@selector(renameButtonClicked:) forControlEvents:UIControlEventValueChanged];
    [renameButton setSegmentedControlStyle:UISegmentedControlStyleBar];
    [renameButton setMomentary:YES];
    [renameButton setTintColor:[UIColor lightGrayColor]];
    [cell.contentView addSubview:renameButton];

    objc_setAssociatedObject(renameButton, "cell", cell, OBJC_ASSOCIATION_ASSIGN);

    [renameButton release];

return cell;

Selector method:

- (void)renameButtonClicked:(id)sender {

isInEditMode = !isInEditMode;
[self setToolbarUserInterface];
[self setTableViewUserInterface];

while ([selectedItems count] > 0) {
    [selectedItems removeLastObject];
}

UITableViewCell *cell = objc_getAssociatedObject(sender, "cell");
int index = [[self.tableView indexPathForCell:cell] row];

NSLog(@"Index value : %d",index);

NSString *newPath = [path stringByAppendingPathComponent:[items objectAtIndex:index]];

TextInputViewController *textInput = [[TextInputViewController alloc] init];
[textInput setPath:newPath Parent:parent andType:5];
[self.navigationController pushViewController:textInput animated:YES];
}

And don't forget to import runtime.h

#import <objc/runtime.h>
shftd
  • 1
  • 1
0

My approach would be this :

  1. Create a custom button class which inherits a class depending on ui element you're using which triggers an action, in your case it's UISegmentedControl.
  2. Then add a property to hold a reference to its index path.
  3. While you are creating your UISegmentedControl set its index path.
  4. In your action method, you can get simply its index path.

I think it's more convenient way to do what you want to do, because let's say, you want to change the view hierarchy of your cell. It's a good chance to your code needs to be changed. Also, get third superview of a UIKit element is never a good idea.

limon
  • 3,222
  • 5
  • 35
  • 52
-1

The clear way of getting the indexpath in this case would be:

NSIndexPath *index = [myTableView indexPathForCell:(UITableViewCell *)[[sender superview]superview]];
Balaji Kandasamy
  • 4,446
  • 10
  • 40
  • 58
Aish
  • 189
  • 7