【问题标题】:Custom UITableViewCell with UIButton: which button has been clicked?带有 UIButton 的自定义 UITableViewCell:单击了哪个按钮?
【发布时间】:2012-03-06 07:34:23
【问题描述】:

我正在使用最新的 SDK 和 XCode 4.2 开发一个 iOS 4 应用程序。

我有一个 UITableView 带有部分和自定义 UITableViewCell。每个单元格都有一个 UIButton,所有这些按钮都具有相同的 UIControlEventTouchUpInside 目标。

这是我的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString* cellIdentifier = @"CalendarCell";

    CalendarEventCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil)
    {
        NSArray* topLevelObjects =  [[NSBundle mainBundle] loadNibNamed:@"CalendarEventCell" owner:nil options:nil];

        for(id currentObject in topLevelObjects)
        {
            if ([currentObject isKindOfClass:[CalendarEventCell class]])
            {
                cell = (CalendarEventCell *)currentObject;
                [cell.addToCalendarButton addTarget:self action:@selector(addEventToiCal) forControlEvents:UIControlEventTouchUpInside];
                break;
            }
        }
    }
...
}

当用户触摸该按钮内部时,我如何知道单击的单元格是在哪个部分和哪一行?

【问题讨论】:

标签: ios uitableview uibutton


【解决方案1】:

在按钮上放置一个标签。例如:

CalendarEventCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (cell == nil)
{
    NSArray* topLevelObjects =  [[NSBundle mainBundle] loadNibNamed:@"CalendarEventCell" owner:nil options:nil];

    for(id currentObject in topLevelObjects)
    {
        if ([currentObject isKindOfClass:[CalendarEventCell class]])
        {
            cell = (CalendarEventCell *)currentObject;
            [cell.addToCalendarButton addTarget:self action:@selector(addEventToiCal) forControlEvents:UIControlEventTouchUpInside];
            break;
        }
    }
}
cell.addToCalendarButton.tag = ((indexPath.section & 0xFFFF) << 16) |
                               (indexPath.row & 0xFFFF);

您需要将选择器更改为@selector(addEventToiCal:),并将方法更新为-(void) addEventToiCal:(UIButton *)sender

然后您可以将如下内容添加到-addEventToiCal:

if (!([sender isKindOfClass:[UIButton class]]))
    return;
NSUInteger section = ((sender.tag >> 16) & 0xFFFF);
NSUInteger row     = (sender.tag & 0xFFFF);
NSLog(@"Button in section %i on row %i was pressed.", section, row);

【讨论】:

  • 您也可以将方法声明为- (void) addEventToiCal:(UIButton *)sender,然后删除第一行。
  • @MisterJack 我曾争论过这样写。由于您似乎支持该想法,因此我更新了答案以反映您的建议。
  • 感谢您的回答。我需要 indexPath.section 和 indexPath.row。
  • 标记方法很简单,但不能很好地扩展,特别是当向必须在控制器中识别的单元格添加更多控件并且您需要在行完成后更新标签时添加和删​​除。我已经看到它导致错误/问题太多次了。
  • @VansFannel 您可以使用类似tag = ((indexPath.section &amp; 0xFFFF) &lt;&lt; 16) | (indexPath.row &amp; 0xFFFF); 的方式对部分和行进行编码,然后使用类似以下方式对其进行解码:section = ((tag &gt;&gt; 16) &amp; 0xFFFF); row = (tag &amp; 0xFFFF);
【解决方案2】:

将按钮的目标设置为单元格中的方法,而不是将目标设置为控制器本身,使用tappedButton:(UIButton *)button inCell:(UITableViewCell *)cell 之类的方法为单元格创建委托协议,并将控制器设置为单元格的委托。在目标方法中调用该委托方法。

然后在控制器的委托方法实现中,您可以通过调用UITableViewtableView:indexPathForCell:找到单元格的NSIndexPath

【讨论】:

  • 将部分和行传递给tappedButton: 方法而不是调用tableView:indexPathForCell: 可能更容易,不是吗?
  • 那么你必须将单元格的NSIndexPath 作为它的 ivar/property - 这也是可能的。但是你不必要地复制了你必须额外维护的数据——当细胞死亡时释放它,例如当细胞死亡时更新它。上面的单元格被添加或删除等等。但是,如果您在运行 tableView:indexPathForCell: 时遇到性能问题(这不太可能),您当然可以使用该“快捷方式”。
【解决方案3】:

cellForRowAtIndexPath 方法中那样为按钮分配标签值

  1. cell.addToCalendarButton.tag=indexPath.row
  2. 当您将方法添加到按钮时,也会发送发送者,因此将方法分配给按钮。

    [cell.addToCalendarButton addTarget:self action:@selector(addEventToiCal:)forControlEvents:UIControlEventTouchUpInside];

  3. 在您的方法中,像这样读取相关行

    -(IBAction)addEventToiCal:(id)sender { NSLog("当前行是 %d",[sender tag]); }

如果你想现在关于该部分然后 indexPath 做这样的事情然后

- (void)addEventToiCal:(id)sender event:(id)event
{
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];

   NsLog("value of indePath.section %d ,indexPath.row %d",indexPath.section,indexPath.row);

}

像这样在 cellforRowAtIndexPath 分配你的方法。

[cell.addToCalendarButton addTarget:self action:@selector(addEventToiCal:event:)forControlEvents:UIControlEventTouchUpInside];

【讨论】:

  • 感谢您的回答。我需要 indexPath.section 和 indexPath.row。
【解决方案4】:

BNRXIBCell 是一个出色的解决方案,适用于 iOS 5 及更高版本。它是一个 UITableViewCell 子类,旨在被子类化,以将操作消息从单元子视图转发到控制器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多