Ios 动态表中自定义单元格中的按钮:如何知道操作方法中的哪一行?

Ios 动态表中自定义单元格中的按钮:如何知道操作方法中的哪一行?,ios,objective-c,cocoa,Ios,Objective C,Cocoa,我有一个动态内容表。在原型单元中,我有一个按钮。在该按钮的动作方法中,如何确定按下了哪一行的按钮 (我知道,例如,在segue方法中,可以通过查询表视图的选定路径来确定按下了哪一行,但在这种情况下,实际上没有选择任何行。)可以使用标记、关联对象或superview技巧 这是一个有三个答案的例子 标签 关联对象 您可以使用标记、关联对象或superview欺骗 这是一个有三个答案的例子 标签 关联对象 当然,也有使用标记s或者在单元格中存储索引XPath的方法 我更喜欢使用类似于下面的东西,我认为

我有一个动态内容表。在原型单元中,我有一个按钮。在该按钮的动作方法中,如何确定按下了哪一行的按钮


(我知道,例如,在segue方法中,可以通过查询表视图的选定路径来确定按下了哪一行,但在这种情况下,实际上没有选择任何行。)

可以使用标记、关联对象或superview技巧

这是一个有三个答案的例子

标签 关联对象
您可以使用标记、关联对象或superview欺骗

这是一个有三个答案的例子

标签 关联对象
当然,也有使用
标记
s或者在单元格中存储
索引XPath
的方法

我更喜欢使用类似于下面的东西,我认为比上面更干净。您可以将其添加到类别UITableViewController

- (NSIndexPath *)indexPathForCellSubview:(UIView *)subview
{
    if (subview) {
        UITableViewCell *cell = [self tableViewCellForCellSubview:subview];
        return [self.tableView indexPathForCell:cell];
    }
    return nil;
}

- (UITableViewCell *)tableViewCellForCellSubview:(UIView *)subview
{
    if (subview) {
        UIView *superView = subview.superview;
        while (true) {
            if (superView) {
                if ([superView isKindOfClass:[UITableViewCell class]]) {
                    return (UITableViewCell *)superView;
                }
                superView = [superView superview];
            } else {
                return nil;
            }
        }
    } else {
        return nil;
    }
}
使用@staticVoidMan的建议进行编辑:

更简洁的实现:

- (UITableViewCell *)tableViewCellForCellSubview:(UIView *)subview
{
    UIView *checkSuperview = subview.superview;

    while (checkSuperview) {
        if ([checkSuperview isKindOfClass:[UITableViewCell class]]) {
            break;
        } else {
            checkSuperview = checkSuperview.superview;
        }
    }
    return (UITableViewCell *)checkSuperview;
}

当然,也有使用
标记
s或者在单元格中存储
索引XPath
的方法

我更喜欢使用类似于下面的东西,我认为比上面更干净。您可以将其添加到类别UITableViewController

- (NSIndexPath *)indexPathForCellSubview:(UIView *)subview
{
    if (subview) {
        UITableViewCell *cell = [self tableViewCellForCellSubview:subview];
        return [self.tableView indexPathForCell:cell];
    }
    return nil;
}

- (UITableViewCell *)tableViewCellForCellSubview:(UIView *)subview
{
    if (subview) {
        UIView *superView = subview.superview;
        while (true) {
            if (superView) {
                if ([superView isKindOfClass:[UITableViewCell class]]) {
                    return (UITableViewCell *)superView;
                }
                superView = [superView superview];
            } else {
                return nil;
            }
        }
    } else {
        return nil;
    }
}
使用@staticVoidMan的建议进行编辑:

更简洁的实现:

- (UITableViewCell *)tableViewCellForCellSubview:(UIView *)subview
{
    UIView *checkSuperview = subview.superview;

    while (checkSuperview) {
        if ([checkSuperview isKindOfClass:[UITableViewCell class]]) {
            break;
        } else {
            checkSuperview = checkSuperview.superview;
        }
    }
    return (UITableViewCell *)checkSuperview;
}
最佳方法:

-(void)buttonMethod:(UIButton *)sender event:(UIEvent *)event
{
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint pointCurrent = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForItemAtPoint:pointCurrent];

    //...
}

附言:前提是你做了如下工作:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //...

    [cell.someButton addTarget:self
                        action:@selector(buttonMethod:event:)
              forControlEvents:UIControlEventTouchUpInside];

    //...
}
最佳方法:

-(void)buttonMethod:(UIButton *)sender event:(UIEvent *)event
{
    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint pointCurrent = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForItemAtPoint:pointCurrent];

    //...
}

附言:前提是你做了如下工作:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //...

    [cell.someButton addTarget:self
                        action:@selector(buttonMethod:event:)
              forControlEvents:UIControlEventTouchUpInside];

    //...
}


超级视野骗局!我认为这是一种黑客行为,与干净的代码相反。而且。。。会在iOS6中崩溃(如果有人在乎的话)是的,这是superview的诡计。我认为这比使用标记或相关对象要简单得多。不过,我打算结合这种查找superview的方法,并在表格单元格上设置标记。原则上,这似乎工作正常,但它崩溃iOS6到底有什么问题?@NeilCoffey:在iOS6中,
按钮的立即
超级视图
是一个子类
UITableViewCell
。在iOS7中,(他们稍微改变了一点),
按钮的立即
超级视图
是一个名为
UITableViewCellScrollView
的私有类,它的
superview
是必需的
UITableViewCell
。因此,当您执行
按钮.superview.superview
(在iOS6中)时,它返回
UITableView
,并在您尝试在其上实现
UITableViewCell
方法时崩溃(我没有测试过他的方法,但当我看到
superview
时,我变得过于谨慎,但看起来他正在处理这个案例……它在iOS6中崩溃了吗?)超级视野骗局!我认为这是一种黑客行为,与干净的代码相反。而且。。。会在iOS6中崩溃(如果有人在乎的话)是的,这是superview的诡计。我认为这比使用标记或相关对象要简单得多。不过,我打算结合这种查找superview的方法,并在表格单元格上设置标记。原则上,这似乎工作正常,但它崩溃iOS6到底有什么问题?@NeilCoffey:在iOS6中,
按钮的立即
超级视图
是一个子类
UITableViewCell
。在iOS7中,(他们稍微改变了一点),
按钮的立即
超级视图
是一个名为
UITableViewCellScrollView
的私有类,它的
superview
是必需的
UITableViewCell
。因此,当您执行
按钮.superview.superview
(在iOS6中)时,它返回
UITableView
,并在您尝试在其上实现
UITableViewCell
方法时崩溃(我没有测试过他的方法,但当我看到
superview
时,我变得过于谨慎,但看起来他正在处理这个案例……它在iOS6中崩溃了吗?)最好是主观的,这种方法过去在调整表视图时失败了。@CrimsonChris:的确是主观的,但我从来没有遇到过这样的问题。你失败的具体案例是什么?(只是好奇)当使用一个表格视图时,它会自动将您刚刚触摸到的单元格滚动到中心。@CrimsonChris:hm。。。我得亲自看看。也许你是在抓住要点之前滚动的(不确定,但我会测试一下),这正是发生的事情。我不想改变这种行为。去了相关的探索,还没有让我失望!最好是主观的,这种方法过去在调整表视图时失败了。@CrimsonChris:的确是主观的,但我从来没有遇到过这样的问题。你失败的具体案例是什么?(只是好奇)当使用一个表格视图时,它会自动将您刚刚触摸到的单元格滚动到中心。@CrimsonChris:hm。。。我得亲自看看。也许你是在抓住要点之前滚动的(不确定,但我会测试一下),这正是发生的事情。我不想改变这种行为。去了相关的探索,还没有让我失望!