如何从 Cell 中获取 UITableViewCell indexPath?
Posted
技术标签:
【中文标题】如何从 Cell 中获取 UITableViewCell indexPath?【英文标题】:How to get UITableViewCell indexPath from the Cell? 【发布时间】:2013-03-20 15:57:22 【问题描述】:我如何从单元格中获取indexPath
中的UITableView
?
我搜索了堆栈溢出和谷歌,但所有信息都在其他方面。有没有办法访问superView
/UITableView
然后搜索单元格?
关于上下文的更多信息:我有两个类,一个叫Cue
,一个叫CueTableCell
(它是UITableViewCell
的子类)CueTableCell
是@987654330的可视化表示@(两个类都有彼此的指针)。 Cue
对象在一个链表中,当用户执行某个命令时,需要选择下一个Cue
的视觉表示(CueTableCell
)。因此Cue
类在列表中的下一个Cue
上调用select
方法,该方法从cell
中检索UITableView
并调用它的selectRowAtIndexPath:animated:scrollPosition:
,为此它需要indexPath
UITableViewCell
.
【问题讨论】:
就像您的其他question 从单元格获取UITableView
- 为什么?这似乎是一个糟糕的设计决策的代码味道 - 没有多少合法的用例让一个单元知道它是 indexPath 或者它是否在屏幕上。
我同意 Paul.s 的评论。你应该说明你为什么要这样做,因为你试图做的可能是个坏主意。
@Paul.s 我在问题中发布了我的程序设计。这可能是不好的编程习惯,在这种情况下,如果您可以提出替代方案,那将非常有帮助。我对可可很陌生,对一般编程也比较陌生。
值得注意的是 indexPathsForVisibleRows 存在 - 当您想知道滚动中的“您在哪里”时,这一点至关重要。
【参考方案1】:
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
它有助于阅读UITableView documentation,即使这被一些人认为是有争议的(参见下面的 cmets)。
单元格不知道它的索引路径是什么。 控制器 应包含任何基于数据模型操作 UI 元素或基于 UI 交互修改数据的代码。 (见MVC。)
【讨论】:
如果您阅读该问题,它会有所帮助。这是来自一个 UITableViewCell,它没有 tableView 属性(并且从所有帐户来看,不应该)。 @voidref 这也有助于思考这个问题;-)。单元不知道它的索引路径是什么。所以这段代码应该在控制器中。有关 MVC 的背景信息,请参阅Cocoa Core Competencies。 从一开始就很明显的人需要正确的答案并不重要。 不回答原始问题。有时细胞需要知道它的路径。例如,如果您在子类单元格上实现了某种形式的滑动操作,您可能需要通知父视图当前正在滑动哪个单元格。一种方法是让 parentView 中的方法循环遍历 tableView 单元格并检查已在单元格中设置的 iVar。更好的方法是让单元格通过委托方法通知 parentView 它是 indexPath ...因此单元格需要知道它是 indexPath。所以 Mundi,最好先回答这个问题,然后提出你的观点。 索引路径是单元格和数据模型之间的“胶水”,属于控制器。上面的长评论实际上是错误的。 @wuf810 ...因为控制器知道单元格和索引路径之间的关系,所以单元格不知道(也不应该)。【参考方案2】:在你的 UITableViewCell 中尝试这个:
NSIndexPath *indexPath = [(UITableView *)self.superview indexPathForCell: self];
编辑:似乎这不适用于 ios 8.1.2 及更高版本。感谢克里斯普林斯指出。
【讨论】:
在 iOS 8.1.2 中,表格视图单元格的父视图是 UITableViewWrapperView 类型。它的超级视图是表视图类型。但我认为我们在这里踏上了危险的道路...... 这一切都回到了“单元格不知道它的索引路径是什么”。争论。访问 superview 几乎总是一种 hack,一段时间后它不起作用也就不足为奇了。 完全正确fatuhoku,知道索引路径不是cell的问题【参考方案3】:在单元格的 .h 文件中放置一个弱 tableView 属性,例如:
@property (weak,nonatomic)UITableView *tableView;
在 cellForRowAtIndex 方法中分配属性,如:
cell.tableView = tableView;
现在只要你需要 cell 的 indexPath:
NSIndexPath *indexPath = [cell.tableView indexPathForCell:cell];
【讨论】:
这是可行的,因为我们只存储了一个指向 tableView 本身的指针,但是 indexPathForCell 可靠吗?我认为这仅提供可见单元格的 indexPath 吗?【参考方案4】:你可以试试这个简单的技巧:
在你的UITableViewCell
课堂上:
@property NSInteger myCellIndex; //or add directly your indexPath
在你的 cellForRowAtIndexPath
方法上:
...
[cell setMyCellIndex : indexPath.row]
现在,您可以在任何地方检索您的单元格索引
【讨论】:
您需要记住在重新排序或删除单元格后手动更新此信息。【参考方案5】:为了解决那些说“这是个坏主意”的人,在我的情况下,我的需要是我的UITableViewCell
上有一个按钮,按下时是一个转场到另一个视图。由于这不是单元格本身的选择,[self.tableView indexPathForSelectedRow]
不起作用。
这给我留下了两个选择:
-
将我需要传递到视图中的对象存储在表格单元格本身中。虽然这可行,但它会破坏我拥有
NSFetchedResultsController
的意义,因为我没有 em> 希望将所有对象存储在内存中,尤其是在表很长的情况下。
使用索引路径从 fetch 控制器中检索项目。 是的,我必须通过 hack 找出 NSIndexPath
看起来很难看,但它最终比将对象存储在内存中便宜。
indexPathForCell:
是正确的使用方法,但我会这样做(假设此代码在UITableViewCell
的子类中实现:
// uses the indexPathForCell to return the indexPath for itself
- (NSIndexPath *)getIndexPath
return [[self getTableView] indexPathForCell:self];
// retrieve the table view from self
- (UITableView *)getTableView
// get the superview of this class, note the camel-case V to differentiate
// from the class' superview property.
UIView *superView = self.superview;
/*
check to see that *superView != nil* (if it is then we've walked up the
entire chain of views without finding a UITableView object) and whether
the superView is a UITableView.
*/
while (superView && ![superView isKindOfClass:[UITableView class]])
superView = superView.superview;
// if superView != nil, then it means we found the UITableView that contains
// the cell.
if (superView)
// cast the object and return
return (UITableView *)superView;
// we did not find any UITableView
return nil;
附:我的真实代码确实从表格视图中访问了所有这些,但我给出了一个示例,说明为什么有人可能想直接在表格单元格中执行类似的操作。
【讨论】:
【参考方案6】:快速
let indexPath :NSIndexPath? = (self.superview.superview as! UITableView)?.indexPathForCell(self)
【讨论】:
【参考方案7】:这个问题的答案其实对我帮助很大。
我用NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
在我的例子中,sender
是 UITableViewCell
,来自 prepareForSegue
方法。
我使用它是因为我确实没有有TableViewController
但我有UITableView property outlet
我需要找出 Cell
的标题,因此需要知道它的 indexPath。
希望这对任何人都有帮助!
【讨论】:
【参考方案8】:在 iOS 11.0 上,您可以使用UITableView.indexPathForRow(at point: CGPoint) -> IndexPath?
:
if let indexPath = tableView.indexPathForRow(at: cell.center)
tableView.selectRow
(at: indexPath, animated: true, scrollPosition: .middle)
它获取单元格的中心点,然后tableView返回该点对应的indexPath。
【讨论】:
【参考方案9】:试试这个(只有当 tableView 只有一个部分并且所有单元格的高度相同时才有效):
//get current cell rectangle relative to its superview
CGRect r = [self convertRect:self.frame toView:self.superview];
//get cell index
int index = r.origin.y / r.size.height;
【讨论】:
【参考方案10】:Swift 3.0 及以上版本-
如果需要从自定义单元格中获取索引路径-
if let tableView = self.superview as? UITableView
if let indexPath = tableView.indexPath(for: self)
print("Indexpath acquired.")
else
print("Indexpath could not be acquired from tableview.")
else
print("Superview couldn't be cast as tableview")
最好的做法是找出失败的案例。
【讨论】:
【参考方案11】:在你的 UITableViewCell 中尝试这个:
NSIndexPath *indexPath = [(UITableView *)self.superview.superview indexPathForCell:self];
【讨论】:
【参考方案12】:斯威夫特 4.x
为了提供对我的手机的访问权限,我做了这样的事情:
我有一个 UIView 的扩展:
extension UIView
var parentViewController: UIViewController?
var parentResponder: UIResponder? = self
while parentResponder != nil
parentResponder = parentResponder!.next
if let viewController = parentResponder as? UIViewController
return viewController
return nil
然后..在我的单元格类中:
class SomeCell: UITableViewCell
func someMethod()
if let myViewController = self.parentViewController as? CarteleraTableViewController
let indexPath : IndexPath = (myViewController.tableView).indexPath(for: self)!
print(indexPath)
这就是我的全部。
最好的问候。
【讨论】:
以上是关于如何从 Cell 中获取 UITableViewCell indexPath?的主要内容,如果未能解决你的问题,请参考以下文章