【问题标题】:Custom UITableViewCell button action?自定义 UITableViewCell 按钮操作?
【发布时间】:2011-11-15 23:31:55
【问题描述】:

我一直在寻找解决方案,但似乎找不到适合我的解决方案。我有一个自定义单元格,里面有一个按钮。我的问题是如何将 indexPath 传递给 action 方法?

我现在正在做

 [cell.showRewards addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside];

在我的 cellForRowAtIndexPath 方法中,我的方法是:

-(IBAction)myAction:(id)sender{
NSIndexPath *indexPath = [self.tableView indexPathForCell:(MyCustomCell *)[sender superview]];
NSLog(@"Selected row is: %d",indexPath.row);
}

有什么建议吗?谢谢。

【问题讨论】:

  • 你在使用 didSelectRow: 方法吗?

标签: iphone objective-c ios uitableview uibutton


【解决方案1】:

您可以将 indexpath 分配给按钮标签并在您的方法中访问,例如

cell.showRewards.tag = indexPath.row;

-(IBAction)myAction:(id)sender
{
     NSIndexPath *indexPath = [self.tableView indexPathForCell:[sender tag]];
     NSLog(@"Selected row is: %d",indexPath.row);
}

【讨论】:

    【解决方案2】:

    试试这个。

    cell.showRewards.tag=indextPath.row
    

    在 cellforrowatindexpath tableview 的方法中实现这个。

    -(IBAction)myAction:(id)sender{
    UIButton* btn=(UIButton*)sender;
    NSLog(@"Selected row is: %d",btn.tag);
    }
    

    【讨论】:

      【解决方案3】:

      您设置按钮标签值 = indexpath 并在函数中检查它,如果标签值是这样,您就可以做你想做的事

      【讨论】:

        【解决方案4】:
        cell.showRewards.tag = indexPath.row;
        

        -(IBAction)myAction:(id)sender
        {
        UIButton *btn = (UIButton *)sender;
        int indexrow = btn.tag;
        NSLog(@"Selected row is: %d",indexrow);
        }
        

        【讨论】:

          【解决方案5】:

          虽然我觉得为按钮设置tag 是一种方法。您可能需要编写代码以确保每次重用单元格时,都会在按钮对象上更新相应的标记。

          相反,我觉得这可行。试试这个 -

          -(IBAction)myAction:(id)sender
          {
          CGPoint location            = [sender locationInView:self.tableView];
          NSIndexPath *indexPath      = [self.tableView indexPathForRowAtPoint:location];
          UITableViewCell *swipeCell  = [self.tableView cellForRowAtIndexPath:indexPath];
          
          NSLog(@"Selected row: %d", indexPath.row);
          //......
          }
          

          基本上,您所做的是获取点击发生位置相对于您的tableView 的坐标。得到坐标后,tableView 可以使用indexPathForRowAtPoint: 方法给你indexPath。你很好去追求这个......

          瞧,您不仅拥有indexPath,还拥有点击发生的实际单元格。要从您的数据源中获取实际数据(假设它的 NSArray),您可以这样做 -

          [datasource objectAtIndex:[indexPath row]];

          【讨论】:

          • 我正要建议 NSIndexPath * indexPath = [tableView indexPathForRowAtPoint: [[[event touchesForView:button] anyObject] locationInView: tableView]];但这更干净,谢谢!
          • 嗯,我错过了什么吗?实际上是 [sender locationInView:self.tableView];为你工作?
          • 不适合我。我得到 [UIButton locationInView:]: unrecognized selector sent to instanc。
          • 另一个[UIButton locationInView:]:无法识别的选择器
          • 对于那些使用locationInView 导致无法识别的选择器崩溃的人,那是因为您不能在 UIButton 上调用它。您需要添加NSSet *touches = [event touchesForView:sender]UITouch *touch = [touches anyObject],然后在touch 变量上调用locationInView
          【解决方案6】:

          在自定义UITableViewCell 类中:

          [self.contentView addSubview:but_you]; 
          

          cellForRowAtIndexPath方法中你可以写:

          [cell.showRewards addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside];    
          cell.showRewards.tag = indexPath.row;
          

          【讨论】:

          • 添加目标部分是急需的部分,刚刚发现我用#尝试选择器的问题,好像它很快,但多亏了你,我突然意识到我的错误。谢谢。
          【解决方案7】:

          [sender superview] 中,您访问的不是MyCustomCell,而是contentView。 阅读UITableViewCell类参考:

          contentView 返回单元格对象的内容视图。 (只读)

          @property(nonatomic, readonly, retain) UIView *contentView
          

          讨论: UITableViewCell 对象的内容视图是单元格显示的内容的默认超级视图。如果您想通过简单地添加其他视图来自定义单元格,则应将它们添加到内容视图中,以便在单元格进入和退出编辑模式时适当地定位它们。

          修改代码最简单的方法是使用[[sender superview] superview]。 但是,如果您稍后修改单元格并在另一个视图中插入按钮,这将停止工作。 contentView 出现在iPhoneOS 2.0。类似的未来修改将影响您的代码。这就是我不建议使用这种方式的原因。

          【讨论】:

            【解决方案8】:

            我觉得难以置信的是,没有真正的解决方案。

            无论出于何种原因,我发现其他答案中概述的标记方法和“使用屏幕上单元格的视觉位置来识别正确的模型对象”有点脏。

            这里有两种不同的方法来解决这个问题:

            子类化 UITableViewCell

            我采用的解决方案是子类 UITableViewCell

            @interface MyCustomCell : UITableViewCell
            
            @property (nonatomic, strong) Model *myModelObject;
            
            @end
            

            cellForRowAtIndexPath: 中创建单元格时,您可能会使用模型对象来填充单元格数据。在此方法中,您可以将模型对象分配给单元格。

            然后在按钮点击处理程序中:

            MatchTile *cell = (MatchTile *) sender.superview.superview;
            
            if (cell && cell.myModelObject)
            {
                //Use cell.myModelObject
            }
            

            说实话,我对这个解决方案并不是 100% 满意。将域对象附加到这样一个专门的 UIKit 组件感觉是一种不好的做法。

            使用 Objective-C 关联对象

            如果您不想将单元格子类化,则可以使用另一种技巧将模型对象与单元格关联并稍后检索它。

            要从单元格中检索模型对象,您需要一个唯一键来识别它。像这样定义一个:

            static char* OBJECT_KEY = "uniqueRetrievalKey"; 
            

            当您使用模型对象填充单元格时,将以下行添加到您的 cellForRowAtIndexPath: 方法中。这会将您的模型对象与单元对象相关联。

            objc_setAssociatedObject(cell, OBJECT_KEY, myModelObject, OBJC_ASSOCIATION_RETAIN);
            

            然后,您可以在任何引用该单元格的地方检索模型对象:

            MyModelObject *myModelObject = (MyModelObject *) objc_getAssociatedObject(cell, OBJECT_KEY);
            

            在反思中,虽然我选择了第一个(因为我已经对单元进行了子类化),但第二个解决方案可能更简洁一些,因为它仍然是 ViewController 的责任来附加和检索模型对象。 UITableViewCell 不需要知道任何关于它的信息。

            【讨论】:

              【解决方案9】:

              只想添加我认为最好的解决方案:UIView 上的一个类别。

              就这么简单:

              - (void)somethingHappened:(id)sender
              {
                  NSIndexPath *indexPath = [self.tableView indexPathForCell:[sender parentCell]];
              
                  // Your code here...
              }
              

              只需在 UIView 上使用这个类别:

              @interface UIView (ParentCell)
              
              - (UITableViewCell *)parentCell;
              
              @end
              
              @implementation UIView (ParentCell)
              
              - (UITableViewCell *)parentCell
              {
                  UIView *superview = self.superview;
                  while( superview != nil ) {
                      if( [superview isKindOfClass:[UITableViewCell class]] )
                          return (UITableViewCell *)superview;
              
                      superview = superview.superview;
                  }
              
                  return nil;
              }
              
              @end
              

              【讨论】:

              • 这实际上是一个不错的类别,它还可以处理 iOS 7 和
              【解决方案10】:

              - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法中编写如下代码:

                [cell.zoomButton addTarget:self action:@selector(navigateAction:) forControlEvents:UIControlEventTouchUpInside];
              cell.zoomButton.tag=indexPath.row;
              

              然后写一个这样的方法:

              -(IBAction)navigateAction:(id)sender
              {
              UIButton *btn = (UIButton *)sender;
              int indexrow = btn.tag;
              NSLog(@"Selected row is: %d",indexrow);
              
              currentBook = [[bookListParser bookListArray] objectAtIndex:indexrow];
              
              KitapDetayViewController *kitapDetayViewController;
              if(IS_IPHONE_5)
              {
                  kitapDetayViewController = [[KitapDetayViewController alloc] initWithNibName:@"KitapDetayViewController" bundle:Nil];
              }
              
              else
              {
                  kitapDetayViewController = [[KitapDetayViewController alloc] initWithNibName:@"KitapDetayViewController_iPhone4" bundle:Nil];
              }
              kitapDetayViewController.detailImageUrl = currentBook.detailImageUrl;
              kitapDetayViewController.bookAuthor = currentBook.bookAuthor;
              kitapDetayViewController.bookName = currentBook.bookName;
              kitapDetayViewController.bookDescription = currentBook.bookDescription;
              kitapDetayViewController.bookNarrator=currentBook.bookNarrator;
              kitapDetayViewController.bookOrderHistory=currentBook.bookOrderDate;
              int byte=[currentBook.bookSizeAtByte intValue];
              int mb=byte/(1024*1024);
              NSString *mbString = [NSString stringWithFormat:@"%d", mb];
              kitapDetayViewController.bookSize=mbString;
              kitapDetayViewController.bookOrderPrice=currentBook.priceAsText;
              kitapDetayViewController.bookDuration=currentBook.bookDuration;
              kitapDetayViewController.chapterNameListArray=self.chapterNameListArray;
              // [[bookListParser bookListArray ]release];
              [self.navigationController pushViewController:kitapDetayViewController animated:YES];
              }
              

              【讨论】:

                【解决方案11】:

                如果你想要按钮的 indexPath Detecting which UIButton was pressed in a UITableView 描述如何。

                基本上按钮动作变成:

                 - (void)checkButtonTapped:(id)sender
                    {
                        CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
                        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
                        if (indexPath != nil)
                        {
                         ...
                        }
                    }
                

                【讨论】:

                  【解决方案12】:

                  这是“最简单的方法”(在 IOS11 上测试):

                  NSIndexPath *indexPath = [myTable indexPathForRowAtPoint:[[[sender superview] superview] center]];
                  

                  【讨论】:

                    猜你喜欢
                    • 2019-06-02
                    • 1970-01-01
                    • 2012-11-08
                    • 2019-12-15
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多