如何知道UITableview行号

时间:2012-02-14 09:30:15

标签: iphone ios uitableview uiswitch

我有UITableViewCell UISwitch作为每个单元格的附件视图。当我更改单元格中交换机的值时,如何知道交换机在哪一行?我需要切换值更改事件中的行号。

10 个答案:

答案 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];
}
从这里你可以获得行号,你可以将它保存到字符串....