ボタンを押したときにUITableViewセルの行を取得する


84

セルの行を表示するテーブルビューコントローラーがあります。各セルには3つのボタンがあります。各セルのタグに1、2、3の番号を付けました。問題は、ボタンが押されているセルを見つける方法がわからないことです。現在、いずれかのボタンが押された場合にのみ送信者のタグを取得しています。ボタンが押されたときにセルの行番号も取得する方法はありますか?

回答:


278

代わりに、実際にはこの方法を使用する必要があります。

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];

Swiftバージョン:

let buttonPosition = sender.convert(CGPoint(), to:tableView)
let indexPath = tableView.indexPathForRow(at:buttonPosition)

それはあなたindexPathに押されたボタンの位置に基づいてあなたに与えるでしょう。次にcellForRowAtIndexPath、セルindexPath.rowが必要な場合、または行番号が必要な場合に電話をかけます。

妄想的なif (indexPath) ...場合はindexPath、テーブルビューでそのポイントが見つからない場合に備えて、使用する前に確認できます。

Appleがビュー構造を変更することを決定した場合、他のすべての答えは壊れそうです。


8
これ、百万回。他のどれも機能しませんでしたが、これは完璧で、はるかに簡単な解決策でした
2013

2
この答えは正しい解決策であるため機能します。その他は回避策です。ありがとう!
ブルーノフィリップ2013

1
あなたはケースではありません持ってself.tableviewを、このページに私の答えを参照してください。
アショク2013年

1
送信者が間違ったクラスであることに気付いたとき、これは私にとってはうまくいきました。UIButtonが押されるように修正し、現在は機能しています。
lordB8r 2014年

1
メソッドがではconvertPoint:*to*Viewないことを覚えておいてくださいconvertPoint:*from*View。私は... Xcodeのオートコンプリートを使用してのみ動作していないにつながるfromView方式になってしまった
tGilani

40

編集:この答えは時代遅れです。 代わりにこの方法を使用してください


これを試して:

-(void)button1Tapped:(id)sender
{
    UIButton *senderButton = (UIButton *)sender;
    UITableViewCell *buttonCell = (UITableViewCell *)[senderButton superview];
    UITableView* table = (UITableView *)[buttonCell superview];
    NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell];
    NSInteger rowOfTheCell = [pathOfTheCell row];
    NSLog(@"rowofthecell %d", rowOfTheCell);
}

編集:contentViewを使用している場合は、代わりにbuttonCellにこれを使用してください。

UITableViewCell *buttonCell = (UITableViewCell *)senderButton.superview.superview;

1
セル自体にサブビューを追加するのではなく、そのcontentViewプロパティにのみ追加することになっているため、このソリューションは実際には機能しません。

1
私は@ H2CO3に同意します。また、スーパービューを参照してこれを行うべきではないと思います。以下のより良い方法をご覧ください:stackoverflow.com/a/16270198/308315
2013

@minimalpop正解を変えていただけませんか?より良いQ / Aを持つために!
Thomas Besnehard 2014

これはiOS7では機能しません。indexPathForRowAtPointを使用してください:以下の回答
オースティン

UICollectionViewで同じバージョンを試しましたが、完全に機能します。どうもありがとう!
クラウス

18

カスタムサブビューを持つセルのindexPathをフェッチするには、この方法をお勧めします-(iOS 7および以前のすべてのバージョンと互換性があります

-(void)button1Tapped:(id)sender {
//- (void)cellSubviewTapped:(UIGestureRecognizer *)gestureRecognizer {
//    UIView *parentCell = gestureRecognizer.view.superview;
    UIView *parentCell = sender.superview;

    while (![parentCell isKindOfClass:[UITableViewCell class]]) {   // iOS 7 onwards the table cell hierachy has changed.
        parentCell = parentCell.superview;
    }

    UIView *parentView = parentCell.superview;

    while (![parentView isKindOfClass:[UITableView class]]) {   // iOS 7 onwards the table cell hierachy has changed.
        parentView = parentView.superview;
    }


    UITableView *tableView = (UITableView *)parentView;
    NSIndexPath *indexPath = [tableView indexPathForCell:(UITableViewCell *)parentCell];

    NSLog(@"indexPath = %@", indexPath);
}

これも必要ありませんself.tablview

また、カスタムサブビューに追加されたUIGestureRecognizerの@selectorを介して同じものが必要な場合に役立つ、コメント付きのコードに注意してください。


uitableviewcontrollerにあるデータが必要な場合はどうなりますか?
iosMentalist 2014年

良い答えです。検索バーがあり、現在どのテーブルが使用されているかを知りたい場合は、これも使用できます。
Suraj K Thomas

テーブルセルの階層が変更されましたか?どのような変更が行われたのか、さらに変更できるのかを理解するのを手伝ってもらえますか?
Kamaldeep singh Bhatia 2016年

3

2つの方法があります:

  1. @ H2CO3は正しいです。@ user523234が提案したことを実行できますが、わずかな変更を加えるだけで、UIButtonとUITableViewCellの間にあるはずのUITableViewCellContentViewを尊重できます。だから彼のコードを変更するには:

    - (IBAction)button1Tapped:(id)sender
    {
        UIButton *senderButton = (UIButton *)sender;
        UITableViewCellContentView *cellContentView = (UITableViewCellContentView *)senderButton.superview;
        UITableViewCell *tableViewCell = (UITableViewCell *)cellContentView.superview;
        UITableView* tableView = (UITableView *)tableViewCell.superview;
        NSIndexPath* pathOfTheCell = [tableView indexPathForCell:tableViewCell];
        NSInteger rowOfTheCell = pathOfTheCell.row;
        NSLog(@"rowofthecell %d", rowOfTheCell);
    }
    
  2. カスタムUITableViewCell(独自のサブクラス)を作成する場合selfは、IBActionを呼び出すだけです。ストーリーボードを使用するか、セルを設定するときにプログラムでIBAction関数をボタンにリンクできます。

    - (IBAction)button1Tapped:(id)sender
    {
        UITableView* tableView = (UITableView *)self.superview;
        NSIndexPath* pathOfTheCell = [tableView indexPathForCell:self];
        NSInteger rowOfTheCell = pathOfTheCell.row;
        NSLog(@"rowofthecell %d", rowOfTheCell);
    }
    

2

私はあなたがセルにボタンを追加すると仮定しcellForRowAtIndexPath、その後、私は何だろうと、カスタムクラスのサブクラスを作成することでUIButton、追加タグと呼ばれるrowNumberデータを使用して、セルにボタンを追加しながらということ、およびAPPENDを。


3
これは問題ありませんが、そのサブクラスを作成する理由はありませんUIButtontagの共通プロパティですUIView
ロブネイピア2011

私が考えていたか知っていると仮定しないでくださいUIの何かがないUI、補正のための感謝を!
Derek Li

2

別の簡単な方法:

  • tableViewで接点を取得する

  • 次に、ポイントでセルのインデックスパスを取得します

  • インデックスパスには行インデックスが含まれます

コードは次のとおりです。

- (void)buttonTapped:(id)sender {
    UITapGestureRecognizer *tap = (UITapGestureRecognizer *)sender;
    CGPoint point = [tap locationInView:theTableView];

    NSIndexPath *theIndexPath = [theTableView indexPathForRowAtPoint:point];

    NSInteger theRowIndex = theIndexPath.row;
    // do your stuff here
    // ...
}

1

スウィフト3

注:これは、メタがそのような編集に眉をひそめることを除いて、上記の受け入れられた答えに実際に入るはずです。

@IBAction func doSomething(_ sender: UIButton) {
   let buttonPosition = sender.convert(CGPoint(), to: tableView)
   let index = tableView.indexPathForRow(at: buttonPosition)
}

2つのマイナーなコメント:

  1. デフォルトの関数の送信者タイプはAnyで、変換はありません。
  2. CGPointZeroはCGPoint()に置き換えることができます

完璧に動作します。

0

1つの解決策は、ボタンのスーパービューのタグ、またはビュー階層のさらに上位のタグをチェックすることです(ボタンがセルのコンテンツビューにある場合)。


0

迅速にコードを共有したい-

extension UITableView
{
    func indexPathForCellContainingView(view1:UIView?)->NSIndexPath?
    {
        var view = view1;
        while view != nil {
            if (view?.isKindOfClass(UITableViewCell) == true)
            {
                return self.indexPathForCell(view as! UITableViewCell)!
            }
            else
            {
                view = view?.superview;
            }
        }
        return nil
    }
}

0

迅速に:

@IBAction func buttonAction(_ sender: UIButton) {
    guard let indexPath = tableView.indexPathForRow(at: sender.convert(CGPoint(), to: tableView)) else {
        return
    }
    // do something
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.