【问题标题】:How to find indexPath for tapped button in tableView Using Seque如何使用 Seque 在 tableView 中找到点击按钮的 indexPath
【发布时间】:2014-07-10 04:20:21
【问题描述】:

我有一个使用原型单元的UITableView

单元格有一个UIButton,它使用Segue 显示一个UIViewController(模态)。

我的问题是:如何将单元格的IndexPath 传递给第二个视图控制器

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([segue.identifier isEqualToString:@"showGamerDetail"]) {

            //its not worked:
            NSIndexPath *indexPath = [self._tableView indexPathForSelectedRow];
            nDetailViewController *destinationViewController = segue.destinationViewController;
            destinationViewController.selectedRowTitle = [gamers objectAtIndex:indexPath.row];

        destinationViewController.indexPath = indexPath;
        destinationViewController.delegate = self;
    }

【问题讨论】:

    标签: ios uitableview


    【解决方案1】:

    非常简单的解决方案,如果您想指向所选单元格的相同segue。

    - (IBAction)buttonPressed:(id)sender {
    
        CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    
        [self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
    
    }
    

    【讨论】:

      【解决方案2】:

      暂时忘记您正在使用情节提要,让我们尝试遵循最佳方法。

      您有多种解决方案,但在我看来,只有其中一种是最佳的:delegation pattern

      首先,您应该扩展您的单元格,并在用户按下按钮时使用委托返回单元格。然后,您应该使用indexPathForCell 来获取indexPath

      让我们看看方法:

      按按钮位置的单元格

      - (void)buttonClicked:(id)sender
        CGPoint buttonPosition = [sender convertPoint:CGPointZero
                                         toView:self.tableView];
        NSIndexPath *tappedIP = [self.tableView indexPathForRowAtPoint:buttonPosition];
      
        // When necessary 
        // UITableViewCell *clickedCell = [self.tableView cellForRowAtIndexPath:tappedIP];
      }
      

      上述解决方案无疑是实施最快的,但从设计/架构的角度来看并不是最好的。此外,您会得到indexPath,但您需要计算所有其他信息。这是一个很酷的方法,但并不是最好的。

      在按钮超级视图上按 while 循环

      // ContactListViewController.m
      
      - (IBAction)emailContact:(id)sender {
          YMContact *contact = [self contactFromContactButton:sender];
          // present composer with `contact`...
      }
      
      - (YMContact *)contactFromContactButton:(UIView *)contactButton {
          UIView *aSuperview = [contactButton superview];
          while (![aSuperview isKindOfClass:[UITableViewCell class]]) {
              aSuperview = [aSuperview superview];
          }
          YMContactCell *cell = (id) aSuperview;
          NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
          return [[self fetchedResultsController] objectAtIndexPath:indexPath];
      }
      

      以这种方式获取单元格的性能不如前者,也不优雅。

      按按钮标记的单元格

      - (CustomCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
      
          CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
          cell.theLabel.text = self.theData[indexPath.row];
          cell.button.tag = indexPath.row;
          [cell.button addTarget:self action:@selector(doSomething:) forControlEvents:UIControlEventTouchUpInside];
          return cell;
      }
      
      -(void)doSomething:(UIButton *) sender {
          NSLog(@"%@",self.theData[sender.tag]);
          //sender.tag will be equal to indexPath.row
      }
      

      绝对没有。使用标签似乎是一个很酷的解决方案,但是控件的 标签可以用于其他原因,例如下一个响应者等。我不喜欢这种方法。

      单元格设计模式

      // YMContactCell.h
      @protocol YMContactCellDelegate
      - (void)contactCellEmailWasTapped:(YMContactCell*)cell;
      @end
      
      @interface YMContactCell
      @property (weak, nonatomic) id<YMContactCellDelegate> delegate;
      @end
      
      // YMContactCell.m
      - (IBAction)emailContact:(id)sender {
          [self.delegate contactCellEmailWasTapped:self];
      }
      
      // ContactListViewController.m
      - (void)contactCellEmailWasTapped:(YMContactCell*)cell;
          NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
          YMContact *contact = [[self fetchedResultsController] objectAtIndexPath:indexPath];
          // present composer with `contact` ...
      }
      

      这是我最喜欢的解决方案。 使用delegationblocks 是一种非常好的方法,您可以传递所有需要的参数。事实上,您可能想直接发回所需的信息,而无需稍后计算。

      享受;)

      【讨论】:

      • 真正有用的答案
      • Cell by button tag 是最好的方法并且易于实施。你摇滚兄弟。
      • 谢谢伙计,但我不得不说不是。您不应该诚实地依赖标签,因为它可以用于其他目的。从正确的设计角度来看,最后一种方法对我来说是最好的。
      【解决方案3】:

      先做一个全局int变量selecteIndex

      在你的单元格中,给你的按钮标签类似于单元格的indexPath.row

      例如btn.tag = indexPath.row;

      点击该按钮时的 assing & call 操作

      [btn addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
      
      -(void)buttonClicked:(id)sender
      {
          UIButton *btn = (UIButton*)sender;
          selectedIndex = btn.tag;
          [self performSegueWithIdentifier:@"segueName" sender:self];
      }
      

      然后在你的视图末尾写下这个函数

      - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
      {
          if ([segue.identifier isEqualToString:@"segueName"]) {
              viewController *dvc = (viewController *)[segue destinationViewController];
              [dvc setSelected:selectedIndex];
          };
      }
      

      【讨论】:

      • 这只是给出了索引路径所在的行,而不是索引路径本身。
      • 我有时使用 button.titleLabel.tag 来存储行号或节号。您可以将行存储在 button.tag 中,将部分存储在 button.titleLabel 标签中,或者类似的变体。
      猜你喜欢
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多