如何从 UIButton 操作方法获取 UITableViewCell 对象?
Posted
技术标签:
【中文标题】如何从 UIButton 操作方法获取 UITableViewCell 对象?【英文标题】:How can I get UITableViewCell object from a UIButton action method? 【发布时间】:2012-07-26 12:47:17 【问题描述】:我有一个 UITableView,我在其中添加了一个 UIButton 作为每个单元格的附件视图。请注意,我将按钮的标签设置为当前行以供将来使用。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if(cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cellButton = [UIButton buttonWithType:UIButtonTypeCustom];
cellButton.frame = CGRectMake(0, 0, 30, 30);
[cellButton setBackgroundImage:[UIImage imageNamed:@"cellButton.png"] forState:UIControlStateNormal];
[cellButton addTarget:self action:@selector(cellButtonAction:) forControlEvents:UIControlEventTouchUpInside];
cellButton.tag = indexPath.row; // <= Will use this in the next method
cell.accessoryView = cellButton;
//Load cell with row based data
return cell;
现在,当点击其中一个按钮时,我需要对单元格进行更改。所以我实现了 cellButtonAction 我使用标签取回单元格:
-(void)editCommentButtonAction:(id)sender
UIButton *button = sender;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:button.tag inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self makeChangesToCell:cell];
但这似乎是一种非常迂回的方式。有没有更清洁的方法来做到这一点?
【问题讨论】:
Detecting which UIButton was pressed in a UITableView的可能重复 没有更清洁的方法 - 我们都是这样做的。顺便说一句,移动这一行“cellButton.tag = indexPath.row;”在 if(cell == nil) 之外,所以它总是完成(否则标签在你回收时永远不会更新)。 @DavidH 这不是我们所有人的做法,标签很烂。请参阅我的回答here,恕我直言,这是一种非常优越的方法。 @jrturton 你说得很好——另一种可能的更好的方法。也就是说,我个人倾向于将标签用于各种事情 - 找到特定标签来表示更新价格等。所以我很乐意这样做。正如大家所说,YMMV :-) jrturton,好主意! @DavidH 已经完成了任务。但是,如果有很多部分,你会怎么做?那这个方案就行不通了! 【参考方案1】:所以假设按钮直接在contentView
中:
向“sender
”(即按钮)询问其父视图,即单元格的 contentView
向该视图询问其superView
,即单元格
向 tabview 询问此单元格的索引:
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell
编辑:实际上,我现在使用一个通用的方法或函数,它只是遍历超级视图,寻找一个 UITableViewCell 或 UICollectionViewCell 的“KindOf”视图。像冠军一样工作!
Swift 中的代码:
func containingUITableViewCell(tableView: UITableView, var view: UIView) -> (UITableViewCell, NSIndexPath)?
while let v = view.superview
view = v
if view.isKindOfClass(UITableViewCell.self)
if let cell = view as? UITableViewCell, let indexPath = tableView.indexPathForCell(cell)
return (cell, indexPath)
else
return nil
return nil
func containingUICollectionViewCell(collectionView: UICollectionView, var view: UIView) -> (UICollectionViewCell, NSIndexPath)?
while let v = view.superview
view = v
if view.isKindOfClass(UICollectionViewCell.self)
if let cell = view as? UICollectionViewCell, let indexPath = collectionView.indexPathForCell(cell)
return (cell, indexPath)
else
return nil
return nil
【讨论】:
【参考方案2】:您可以以更简单的方式进行操作。您将使用 sender 参数获取表格视图单元格。 检查以下代码。
-(void)editCommentButtonAction:(id)sender
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell*)[button superview];
[self makeChangesToCell:cell];
这里,
-
您正在将
id
类型的sender
转换为UIButton
你正在调用那个按钮的getter superview
,它会给你UITableViewCell
进行自定义。
【讨论】:
【参考方案3】:您可以通过以下方式获取单元格。
-(void)editCommentButtonAction:(id)sender
NSIndexPath* indexPath = 0;
//Convert the bounds origin (0,0) to the tableView coordinate system
CGPoint localPoint = [self.tableView convertPoint:CGPointZero fromView:sender];
//Use the point to get the indexPath from the tableView itself.
indexPath = [self.tableView indexPathForRowAtPoint:localPoint];
//Here is the indexPath
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self makeChangesToCell:cell];
【讨论】:
【参考方案4】:我有同样的情况,问题是我的表格单元格中有一个 imageView,我想获得包含我点击的 imageview 的单元格..
//MyCell is subclass of UITableViewCell
if ([[[[sender view] superview] superview] isKindOfClass:[MyCell class]])
MyCell *cell = (MyCell *)[[[sender view] superview] superview];
NSIndexPath *cellIndexPath = [myTable indexPathForCell:cell];
NSLog(@"cellIndexPath: %@ - %@",cellIndexPath, [videoURLArray objectAtIndex:cellIndexPath.row]);
[发件人视图] - imageView
[[sender view] superview] -- imageView 的放置位置(在这种情况下,我的 imageView 的 superview 是单元格的 contentView)
[[[sender view] superview] superview] --- contentView 所在的位置 -- 单元格
NSLog 部分应该打印正确的行和被点击的 imageView 的部分。只需修改代码。 ;)
【讨论】:
【参考方案5】:Hello gigahari Use the following code.
- (void)cellStopDownloadButtonClicked:(id)sender
id viewType = [sender superview];
do
viewType = [viewType superview];
while (![viewType isKindOfClass:[CustomCell class]] || !viewType);
CustomCell *cell = (CustomCell *)viewType;
// use the cell
这适用于 ios 6 和 ios 7 等所有情况。在 ios 7 中,单元格中添加了一个额外的视图(内容视图)。
如果你使用 [[sender superview] superview] 在某些情况下会失败。
【讨论】:
【参考方案6】:我通常这样做的方式:
单元格存储给定行或索引路径的数据 使用 -didSelectSomething 或 -didSelectAtIndexPath 方法创建协议: 单元格包含对协议实例的引用,该实例将成为您的数据源 将按钮操作连接到您笔尖中的单元格 让单元格调用代理 不要忘记清理 prepareForReuse 中的单元格。将状态存储在单元格中可能会导致严重的错误,因此请务必在重用时进行清理。标签的东西是一个真正的黑客,如果你有多个部分,它就行不通了。 如果您对 nib 中的视图重新排序,发件人超级视图将中断。
对于这种特殊情况(附件视图),是否有专用的表委托方法?
【讨论】:
以上是关于如何从 UIButton 操作方法获取 UITableViewCell 对象?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过子类化 UIButton 来获取按钮的背景图像名称?
如何从 UIScrollView 获取 UIButton 位置