如果一个UITableViewCell有多个button,哪里是处理触摸事件的最佳位置

我以多列表格式呈现大量数据。 几乎每个列都有一个button(最多4个),每行都是一个UITableViewCell

我怎么能检测到button被触摸,我应该在哪里处理button的触摸事件? 我敢肯定,它不应该是一个didSelectRowAtIndexPath方法。

只要我可以检测到哪个button被按下,我就可以获取特定行中的数据并对其进行处理。 所以,我需要知道该行的indexPath ,以及按下了哪个button。

你可以使用两个属性来inheritanceUIButton,并实现下面的逻辑:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; MyButton *button1 = (MyButton *)[cell viewWithTag:1]; button1.row = indexPath.row; button1.column = 1; // view tag [button1 addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside]; // button2,button3... return cell; } -(void)clickAction:(MyButton *)sender { // now you can known which button NSLog(@"%ld %ld", (long)sender.row, (long)sender.column); } 

一般无误的答案:

  1. 创buildUITableviewcell子类,将单元格的ui元素链接到这个类。
  2. 添加方法configureWithModel:(Model *)模型; / /模型是你想要的细胞代表的信息
  3. 操纵那些信息或
  4. 如果你需要操纵屏幕或其他物体。 在创build单元格时,您需要为表格视图单元格子类提供对其他对象的引用。 (在代码或故事板或笔尖)。

如何处理ios 7中的buttonbutton : UITableViewCell中的button在ios 7下不响应 (将表格单元格select设置为无)

如何链接一个button: http : //oleb.net/blog/2011/06/creating-outlets-and-actions-via-drag-and-drop-in-xcode-4/

如果这四个视图是UIButton那么您将在每个button上收到轻敲事件,或者如果它们不是UIButton ,则应在每个视图上添加UITapGestureReconiser

这里有几个选项。 但我会做以下几点:

在您的自定义单元类中采用委托协议(请参阅: 如何在Objective-C中声明事件和委托? )。 这将处理button的目标select器。 将此消息传回发送者的视图控制器。 要检测它在哪个单元中执行以下操作:

 CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView]; CGRect senderFrame = CGRectMake(buttonPosition.x, buttonPosition.y, sender.frame.size.width, sender.frame.size.height); 

从这里你可以决定做什么。 使用button.x坐标来确定它是哪个button,或者为cellForRowAtIndexPath:每个button指定不同的标记。 或者如果你想抓住单元格的索引path,你可以这样做:

 NSArray *indexPaths = [YOUR_TABLE_VIEW indexPathsForRowsInRect:senderFrame]; NSIndexPath *currentIndexPath = [indexPaths lastObject]; 

因为每个button都有不同的动作,所以在运行时只需要button的indexPath。 这可以通过查看button的超级查看来完成,直到find一个单元格。

 - (IBAction)action1:(UIButton *)button { UITableViewCell *cell = [self cellContainingView:button]; NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; MyDataModel *object = self.objects[indexPath.row]; // perform action1 on the data model object // Now that the data model behind indexPath.row was done, reload the cell [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation: UITableViewRowAnimationAutomatic]; } - (id)cellContainingView:(UIView *)view { if (view == nil) return nil; if ([view isKindOfClass:[UITableViewCell class]]) return view; return [self cellContainingView:view.superview]; } 

在那里:没有代表,没有标签,行动不关心单元的内部。

你仍然想要使用四个button(如果没有更好的名称,称它们为button1,button2,button3和button4)来inheritanceUITableViewCell。 你可以使所有的连接是Interface Builder。 只有在-tableView:cellForRowAtIndexPath:时才需要将对象数据填充到单元格中。

理想情况下,您应该通过UITableViewCell创build一个自定义单元格,并为该单元格中的每个button实施操作。 如果你的视图控制器需要知道这些动作,你可以定义一个协议, MyCustomCellDelegate或类似的,并让你的视图控制器符合该协议。 然后,当用户与其button或其他控件交互时, MyCustomCell将能够发送消息到视图控制器。

如下面的示例代码所示,您可以在storyboard或nib中创build单元格,并将其中一个button的操作挂接到CustomTableCell类的firstButtonAction方法。

此外,您需要将您的视图控制器设置为创buildCustomTableCell对象的委托属性,并在视图控制器类中实现CustomTableCellDelegate的方法buttonActionAtIndex:。 使用传递给此方法的controlIndexInCell参数来确定哪个button可能已经生成了该操作。

  @protocol CustomTableCellDelegate <NSObject> - (void) buttonActionAtIndex:(NSInteger)controlIndexInCell @end 

在CustomTableCell.h类中

  @interface CustomTableCell: UITableViewCell @property (nonatomic, weak) id <CustomTableCellDelegate> delegate - (IBAction) firstButtonAction:(id)sender @end 

在CustomTableCell.m类中

  @implementation CustomTableCell @synthesize delegate - (IBAction) firstButtonAction:(id)sender{ if ([delegate respondToSelector:@selector(buttonActionAtIndex:)]) [delegate buttonActionAtIndex:0]; } @end 

这是个人喜好,我喜欢如何处理这些情况,但我首先将UITableViewCell子类,因为你的表格单元看起来不像一个默认的iOS UITableViewCell。 基本上你有一个自定义的设置,所以你需要一个自定义的类。

从那里你应该在你的头文件中设置你的4个IBAction

 - (IBAction)touchFirstButton; - (IBAction)touchSecondButton; - (IBAction)touchThirdButton; - (IBAction)touchFourthButton; 

您不需要在这些操作中传递发件人,因为您不会在这些方法中使用该对象。 他们正在创build转发电话。

之后,为您的UITableViewSubClass设置一个协议

 @protocol UITableViewSubClassDelegate; 

请记住在@interface声明之前和之前

给你卖一个代表财产

 @property (nonatomic, strong) id<UITableViewSubClassDelegate> delegate; 

最后定义你的实际协议,你需要设置4个方法,每个button1个,并把你的子类作为参数

 @protocol UITableViewSubClassDelegate <NSObject> - (void)forwardedFirstButtonWithCell:(UITableViewSubClass*)cell; - (void)forwardedSecondButtonWithCell:(UITableViewSubClass*)cell; - (void)forwardedThirdButtonWithCell:(UITableViewSubClass*)cell; - (void)forwardedFourthButtonWithCell:(UITableViewSubClass*)cell; @end 

这将被放置在底部的@interface @end部分之外

之后,在你的@interface和@implementation中创build一个configureWithModel:方法,以及你的模型的一个属性

@接口:

 @property (nonatomic, strong) Model *model; - (void)configureWithModal:(Model*)model; 

@implementation:

 - (void)configureWithModal:(Model*)model { self.model = model; // custom UI set up } 

从这里你应该configuration你的@implementation文件中的动作方法来调用委托方法,我只显示第一个,但你会做所有的IBActions

 - (void)configureWithModal:(Model*)model { [self.delegate forwardFirstButtonWithCell:self]; } 

从这里你的自定义单元格设置完成,我们需要回到显示UITableView的UIViewController。 首先进入视图控制器的头文件,并导入您的自定义UITableViewCellSubClass,然后设置类来实现此协议。

它应该看起来像这样

 @interface MYViewController : UIViewController <UITableViewSubClassDelegate> 

从那里你应该进入你的cellForRowAtIndexPath:方法并configuration你的自定义UITableViewCell

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCellSubClass *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"]; cell.delegate = self; Model *cellModel = self.tableData[indexPath.row]; [cell configureWithModel:cellModel]; return cell; } 

现在进入你的单元类并复制粘贴所有的协议方法到你的viewController类。 我将以一个为例。

在你的UIViewController中:

 - (void)forwardedFirstButtonWithCell:(UITableViewSubClass*)cell { Model *cellModel = cell.model; // do stuff with model from outside of the cell } 

做所有的方法,你应该是好的。

请记住所有的#import,所以没有前向声明,并记住将IBActions连接到你的故事板或xib文件。 如果你想为你的表格单元格定制一个xib,你将不得不检查单元格是否为零,然后分配一个新单元格,但是如果你正在使用原型单元格,那么这就足够了。

为了简单起见,我提出了FirstButtonWithCell:但是我会鼓励将名称描述为什么,例如displayPopOverToEnterData或类似的东西。 从那里你甚至可以改变委托协议方法的参数来取代模型

 - (void) displayPopOverToEnterDataWithCell:(UITableViewSubClass*)cell; 

做了

 - (void) displayPopOverToEnterDataWithModel:(Model*)model; 

但是,我不知道你需要从单元访问什么types的信息。 所以更新这些方法,你认为合适的。