我有UITableViewCell
UISwitch
作为每个单元格的附件视图。当我更改单元格中交换机的值时,如何知道交换机在哪一行?我需要切换值更改事件中的行号。
答案 0 :(得分:157)
标签,子类或视图层次结构导航工作太多了!。在您的操作方法中执行此操作:
CGPoint hitPoint = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *hitIndex = [self.tableView indexPathForRowAtPoint:hitPoint];
适用于任何类型的视图,多节表,无论你可以抛出什么 - 只要发件人的来源位于单元格的框架内(感谢rob!),通常就是这种情况。
这里是UITableView Swift扩展名:
extension UITableView {
func indexPath(for view: UIView) -> IndexPath? {
let location = view.convert(CGPoint.zero, to: self)
return self.indexPathForRow(at: location)
}
}
答案 1 :(得分:5)
如果将tag
属性设置为行号(如其他答案所示),则必须每次在tableView:cellForRowAtIndexPath:
中更新它(因为可以为不同的行重用单元格)。
相反,当您需要行号时,您可以将superview
链从UISwitch
(或任何其他视图)向UITableViewCell
走,然后到{{ 1}},并在表视图中询问单元格的索引路径:
UITableView
这不需要static NSIndexPath *indexPathForView(UIView *view) {
while (view && ![view isKindOfClass:[UITableViewCell class]])
view = view.superview;
if (!view)
return nil;
UITableViewCell *cell = (UITableViewCell *)view;
while (view && ![view isKindOfClass:[UITableView class]])
view = view.superview;
if (!view)
return nil;
UITableView *tableView = (UITableView *)view;
return [tableView indexPathForCell:cell];
}
中的任何内容。
答案 2 :(得分:3)
cellForRowAtIndexPath:
中,将控件的tag
属性设置为indexPath.row
答案 3 :(得分:3)
接受的解决方案是一个聪明的黑客。
但是,如果我们可以利用 UIView 上已有的tag
属性,为什么我们需要使用hitpoint?你会说标签只能存储行或部分,因为它只有一个 Int 。
嗯......不要忘记你们的根源(CS101)。 单个 Int 可以存储两个小两倍的整数。 这是一个扩展:
extension Int {
public init(indexPath: IndexPath) {
var marshalledInt: UInt32 = 0xffffffff
let rowPiece = UInt16(indexPath.row)
let sectionPiece = UInt16(indexPath.section)
marshalledInt = marshalledInt & (UInt32(rowPiece) << 16)
marshalledInt = marshalledInt + UInt32(sectionPiece)
self.init(bitPattern: UInt(marshalledInt))
}
var indexPathRepresentation: IndexPath {
let section = self & 0x0000ffff
let pattern: UInt32 = 0xffff0000
let row = (UInt32(self) & pattern) >> 16
return IndexPath(row: Int(row), section: Int(section))
}
}
在tableView(_:, cellForRowAt:)
中,您可以:
cell.yourSwitch.tag = Int(indexPath: indexPath)
然后在动作处理程序中你可以:
func didToogle(sender: UISwitch){
print(sender.tag.indexPathRepresentation)
}
但请注意它的限制:行和部分不得大于65535。(UInt16.max)
我怀疑你的tableView索引会如此高,但万一他们这样做,挑战自己并实施更有效的打包方案。如果我们有一个非常小的部分,我们不需要所有16位来表示一个部分。我们可以使用我们的int布局,如:
{section area length}{all remaining}[4 BITS: section area length - 1]
这是我们的4 LSB 表示截面积的长度 - 1,假设我们为一个部分分配至少1位。因此,如果我们的部分是0,那么行可以占用多达27位([1] [27] [4]),这肯定应该足够了。
答案 4 :(得分:2)
我更喜欢使用子视图,如果你知道你的布局,它通常超级简单,1行短......
NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
多数民众赞成,如果它更嵌套,可以添加更多的超视图。
更多信息:
您要做的就是询问父视图及其父视图,即单元格。然后你问你的tableview你刚刚获得的那个单元格的索引路径。
答案 5 :(得分:1)
执行此操作的一种常见方法是将控件的tag
(在您的情况下为开关)设置为可用于标识行或表示对象的内容。
例如,在tableView:cellForRowAtIndexPath:
中将切换的tag
属性设置为indexPath.row
,在操作方法中,您可以从发件人处获取标记。
就个人而言,我不喜欢这种方法,而更喜欢继承UITableViewCell。 此外,为标记添加“偏移量”以防止与其他视图的标记发生冲突可能是个好主意。
答案 6 :(得分:1)
这篇文章中接受的答案非常好。我想向读者建议以下内容来自@robmayoff,这篇文章也很完美:
- (NSIndexPath *)indexPathForView:(UIView *)view inTableView:(UITableView *)tableView {
while (view && ![view isKindOfClass:[UITableViewCell class]])
view = view.superview;
UITableViewCell *cell = (UITableViewCell *)view;
return [tableView indexPathForCell:cell];
}
有些人断言,由于while循环,这种方法包含太多的计算工作。另一种方法是,将视图的原点转换为表视图坐标空间并调用indexPathForRowAtPoint:
,隐藏更多的工作。
有些人声称这种方法相对于潜在的SDK更改是不安全的。实际上,Apple已经更改了tableview单元格层次结构一次,向单元格添加了contentView
。这种方法在这种改变之前和之后都有效。只要可以通过超视图的链找到视图祖先(这与UIKit中的任何内容一样重要),这就是很好的代码。
答案 7 :(得分:0)
一位同事建议如下,我将其作为UITableView类别:
+(UITableViewCell*)findParentCellForSubview:(UIView*)view
{
while (([view isKindOfClass:[UITableViewCell class]] == NO) && ([view superview] != nil))
view = [view superview];
if ([view superview] != nil)
return (UITableViewCell*)view;
return nil;
}
仍然很黑 - 但它确实有效。
答案 8 :(得分:0)
使用superView的另一种变体。像UIView的类别一样工作。
- (UITableViewCell *)superCell
{
if (!self.superview) {
return nil;
}
if ([self.superview isKindOfClass:[UITableViewCell class]]) {
return (UITableViewCell *)self.superview;
}
return [self.superview superCell];
}
答案 9 :(得分:0)
我不知道多个部分,但我可以给你一个部分......
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger index=indexPath.row;
NSString *string=[[NSString alloc]initWithFormat:@"%ld",(long)index];
}
从这里你可以获得行号,你可以将它保存到字符串....