我有 UITableView
与5 UITableViewCells
. 每个单元格包含 UIButton
,其设置如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
[cell autorelelase];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
[button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:1];
[cell.contentView addSubview:button];
[button release];
}
UIButton *button = (UIButton *)[cell viewWithTag:1];
[button setTitle:@"Edit" forState:UIControlStateNormal];
return cell;
}
我的问题是:在 buttonPressedAction:
方法中,我如何知道按下了哪个按钮 . 我've considered using tags but I'我不确定这是最好的路线 . 我希望能够以某种方式将_1775103标记到控件上 .
- (void)buttonPressedAction:(id)sender
{
UIButton *button = (UIButton *)sender;
// how do I know which button sent this message?
// processing button press for this row requires an indexPath.
}
这样做的标准方法是什么?
Edit:
我通过以下方式解决了这个问题 . 我仍然想知道这是标准的做法还是有更好的方法?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
[cell autorelelase];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
[button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
[button release];
}
UIButton *button = (UIButton *)[cell.contentView.subviews objectAtIndex:0];
[button setTag:indexPath.row];
[button setTitle:@"Edit" forState:UIControlStateNormal];
return cell;
}
- (void)buttonPressedAction:(id)sender
{
UIButton *button = (UIButton *)sender;
int row = button.tag;
}
需要注意的是,我不能在创建单元格时设置标记,因为单元格可能会出列 . 感觉很脏 . 肯定有更好的办法 .
26 回答
在Apple的Accessory示例中,使用了以下方法:
然后在触摸处理程序中检索触摸坐标并从该坐标计算索引路径:
我发现使用superview的方法's superview to obtain a reference to the cell'的indexPath工作得很好 . 感谢iphonedevbook.com(macnsmith)提示link text
这是我如何做到的 . 简洁明了:
在其他地方找到了解决这个问题的好方法,没有弄乱按钮上的标签:
如何使用运行时注入在
UIButton
中发送NSIndexPath
等信息 .1)您需要导入运行时
2)添加静态常量
3)使用以下命令在运行时将
NSIndexPath
添加到按钮:(void)setMetaData:(id)target withObject:(id)newObj
4)按下按钮获取元数据使用:
(id)metaData:(id)target
请享用
要做(@Vladimir)的答案是Swift:
虽然检查
indexPath != nil
给了我手指...... "NSIndexPath is not a subtype of NSString"我会像你说的那样使用tag属性,设置标签如下:
然后在buttonPressedAction中获取标签,如下所示:
要么
虽然我喜欢标记方式...如果你不想出于任何原因使用标签,你可以创建一个预制按钮的成员
NSArray
:然后在渲染tableView之前创建这些按钮并将它们推入数组 .
然后在
tableView:cellForRowAtIndexPath:
函数内部,您可以执行以下操作:然后在
buttonPressedAction:
函数中,你可以做到处理部分 - 我将NSIndexPath存储在自定义UITableViewCell中
IN CLKIndexPricesHEADERTableViewCell.xib
IN IB将UIButton添加到XIB - DONT添加动作!
添加插座@property(保留,非原子)IBOutlet UIButton * buttonIndexSectionClose;
请勿在IB中按CTRL拖动操作(在下面的代码中完成)
在viewForHeaderInSection中(如果你的表只有1个部分,也应该适用于cellForRow ....等)
...使用该部分获取您的单元格的数据
...填入
USER在Section Headers 上按下DELETE按钮并调用此方法
在这个例子中,我添加了一个删除按钮,因此应显示UIAlertView以确认它
我将部分和密钥存储到字典中,存储有关VC中ivar部分的信息
这对我有用,谢谢@Cocoanut
我发现使用superview的superview获取对单元的indexPath的引用的方法非常有效 . 感谢iphonedevbook.com(macnsmith)的提示链接文本
使用Swift 4.2和iOS 12,您可以选择以下完整示例中的一个来解决您的问题 .
#1 . 使用UIView的convert(_:to :)和UITableview的indexPathForRow(at :)
#2 . 使用UIView的convert(_:to :)和UITableview的indexPathForRow(at :)(替代)
这是前一个示例的替代方法,我们将
nil
传递给addTarget(_:action:for:)
中的target
参数 . 这样,如果第一响应者没有实现该动作,它将被发送到响应者链中的下一个响应者,直到找到正确的实现 .#3 . 使用UITableview的indexPath(用于:)和委托模式
在此示例中,我们将视图控制器设置为单元的委托 . 当点击单元格的按钮时,它会触发对委托的适当方法的调用 .
#4 . 使用UITableview的indexPath(for :)和一个用于委托的闭包
这是前一个示例的替代方法,我们使用闭包而不是协议委托声明处理按钮水龙头 .
你可以使用标签模式:
我错过了什么吗?你不能只使用发件人来识别按钮 . 发件人会给你这样的信息:
然后,如果您想要更改按钮的属性,请说明您告诉发件人的背景图片:
如果你需要标签,那么ACBurk的方法就可以了 .
实际上很简单:
对我有用:P
如果要调整目标操作设置,可以在方法中包含事件参数,然后使用该事件的触摸来解析触摸的坐标 . 仍然需要在触摸视图边界中解析坐标,但对于某些人来说这似乎更容易 .
创建一个nsmutable数组并将所有按钮放在该数组usint中[array addObject:yourButton];
在按钮按下方法
当按钮位于表格的页脚(这会阻止您找到“点击的单元格”时),Cocoanuts答案(这有助于我解决这个问题)略有不同:
我总是使用标签 .
你需要子类化
UITableviewCell
并从那里按下按钮 .这很简单;制作一个自定义单元格并按下按钮
将上述方法中的id更改为
(UIButton *)
您可以通过执行sender.tag来获取正在点击哪个按钮的值 .
子类按钮来存储所需的值,也许创建一个协议(ControlWithData或其他东西) . 将按钮添加到表格视图单元格时设置值 . 在您的补足事件中,查看发件人是否遵守协议并提取数据 . 我通常存储对表视图单元格上呈现的实际对象的引用 .
SWIFT 2 UPDATE
在这里's how to find out which button was tapped + send data to another ViewController from that button' s
indexPath.row
因为我最重要的一点!对于那些使用ViewController类并添加了tableView的人,我使用的是ViewController而不是TableViewController,因此我手动添加了tableView以便访问它 .
这是在点击该按钮并传递单元格的时候将数据传递给另一个VC的代码
indexPath.row
请注意,我在使用自定义单元格,此代码非常适合我
Chris Schwerdt的解决方案然后在Swift为我工作:
这个问题有两个部分:
1) Getting the index path of UITableViewCell which contains pressed UIButton
有一些建议,如:
使用索引路径的
row
值在cellForRowAtIndexPath:
方法中更新UIButton
的tag
. 这不是一个好的解决方案,因为它需要连续更新tag
,它不适用于具有多个部分的表视图 .将
NSIndexPath
属性添加到自定义单元格并在cellForRowAtIndexPath:
方法中更新它而不是UIButton
的tag
. 这解决了多节问题,但仍然不好,因为它总是需要更新 .在创建自定义单元格时使用自定义单元格中的父级
UITableView
,并使用indexPathForCell:
方法获取索引路径 . 看起来好一点,不需要在cellForRowAtIndexPath:
方法中更新任何内容,但仍需要在创建自定义单元格时设置弱引用 .使用单元格的
superView
属性获取对父UITableView
的引用 . 无需向自定义单元格添加任何属性,也无需在创建/稍后设置/更新任何内容 . 但是单元格superView
取决于iOS实现细节 . 所以它不能直接使用 .但这可以使用一个简单的循环来实现,因为我们确定所讨论的单元格必须位于UITableView中:
因此,这些建议可以组合成一个简单而安全的自定义单元格方法来获取索引路径:
从现在开始,此方法可用于检测按下哪个
UIButton
.2) Informing other parties about button press event
在内部知道哪个
UIButton
被按下了具有精确索引路径的自定义单元格之后,需要将此信息发送给其他方(很可能是处理UITableView
的视图控制器) . 因此,这个按钮单击事件可以在类似的抽象和逻辑级别处理到UITableView委托的didSelectRowAtIndexPath:
方法 .可以使用两种方法:
a) Delegation: 自定义单元格可以具有
delegate
属性,并可以定义协议 . 按下按钮时,它只执行's delegate methods on it' sdelegate
属性 . 但是,创建它们时,需要为每个自定义单元格设置此delegate
属性 . 作为备选,自定义单元格也可以选择在其上执行其委托方法's parent table view' sdelegate
.b) Notification Center: 自定义单元格可以定义自定义通知名称,并使用
userInfo
对象中提供的索引路径和父表视图信息发布此通知 . 无需为每个单元格设置任何内容,只需为自定义单元格的通知添加观察者即可 .我使用了一个子类
UIButton
的解决方案,我想我应该在这里分享它,Swift中的代码:然后记得在
cellForRow(at:)
更新它的indexPath因此,当响应按钮的事件时,您可以像使用它一样使用它