各セルにボタンアクセサリビューがあるテーブルビューがあります。テーブルはフェッチされた結果コントローラーによって管理され、頻繁に並べ替えられます。ボタンの1つを押して、そのボタンのテーブルビューセルのインデックスパスを取得できるようにしたい。ボタンの行をタグに格納することでこれを何日も機能させようとしていますが、テーブルが並べ替えられると、行が正しくなくなり、タグを正しく並べ替えることができなくなります。ボタンのセルのインデックスパスを追跡する方法に関する新しいアイデアはありますか?
8 に答える
に依存することに不快感を感じる場合button.superview
、この方法は、ここにある他のいくつかの回答よりも少し堅牢である必要があります。
UIButton *button = (UIButton *)sender;
CGRect buttonFrame = [button convertRect:button.bounds toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonFrame.origin];
これはiOS7では機能しなくなりました。代わりにマイク・ウェラーの答えをチェックしてください
- (IBAction)clickedButton:(id)sender {
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview;
UITableView *tableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
}
またはそれより短い:
- (IBAction)clickedButton:(id)sender {
NSIndexPath *indexPath = [(UITableView *)sender.superview.superview indexPathForCell:(UITableViewCell *)sender.superview];
}
どちらもテストされていません!
(既存のすべての回答が示すように)ビュー階層をクロールアップすること.superview
は、物事を行うための本当に悪い方法です。の構造が変更されるとUITableViewCell
(以前に発生したことがあります)、アプリは壊れます。あなたのコードを見る.superview.superview
と、警鐘が鳴るはずです。
ボタンとそのハンドラーをカスタムUITableViewCell
サブクラスに追加して、そこに配置する必要があります。それが属するところです。
セルサブクラスは、標準のデリゲートインターフェイスまたはブロックを介してボタンイベントをデリゲートできます。次のようなものを目指す必要があります。
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = ...;
// ...
cell.onButtonTapped = ^{
[self buttonSelectedAtIndexPath:indexPath];
}
// OR
cell.delegate = self;
// ...
}
(注:ブロックルートを使用する場合は、__weak
保持サイクルを防ぐために自己参照を使用する必要がありますが、例が乱雑になると思いました)。
デリゲートルートを使用する場合は、次のデリゲートメソッドを実装する必要があります。
- (void)cellButtonPressed:(UITableViewCell *)cell
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// ...
}
これで、コードがイベントを処理するときに、適切なコンテキストに完全にアクセスできるようになります。
このインターフェイスをセルクラスに実装するのは簡単です。
UITableViewCellを取得するためにメソッドsuperviewを2回呼び出す必要がある理由がわかりません。
アップデート:
Qiulangに感謝します、今私はそれを手に入れました。
「これは、SDKがUITableViewCell用のUITableViewCellContentViewというプライベートクラスを追加したためです。これは、ボタンのスーパービューになりました。」– qiulang
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
UITableView *curTableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [curTableView indexPathForCell:cell];
私もこれと同じ問題を抱えており、コントロールをトリガーするビューの深さに関係なく機能する単純な再帰メソッドを構築しました。
-(NSIndexPath*)GetIndexPathFromSender:(id)sender{
if(!sender) { return nil; }
if([sender isKindOfClass:[UITableViewCell class]])
{
UITableViewCell *cell = sender;
return [self.tableView indexPathForCell:cell];
}
return [self GetIndexPathFromSender:((UIView*)[sender superview])];
}
-(void)ButtonClicked:(id)sender{
NSIndexPath *indexPath = [self GetIndexPathFromSender:sender];
}
indexPathを取得するためのメソッドを1つ作成しました。これがお役に立てば幸いです。
cellForRowAtIndexPathにボタンアクション(aMethod:)を作成します
-(void) aMethod:(UIButton *)sender
{
// Calling Magic Method which will return us indexPath.
NSIndexPath *indexPath = [self getButtonIndexPath:sender];
NSLog(@"IndexPath: %li", indexPath.row);
NSLog(@"IndexRow: %li", indexPath.section);
}
//ボタンのindexPathを取得するためのMagicメソッドは次のとおりです
-(NSIndexPath *) getButtonIndexPath:(UIButton *) button
{
CGRect buttonFrame = [button convertRect:button.bounds toView:groupTable];
return [groupTable indexPathForRowAtPoint:buttonFrame.origin];
}
私のためにこの完璧な働きを使用してください。
CGPoint center= [sender center];
CGPoint rootViewPoint = [[sender superview] convertPoint:center toView:_tableView1];
NSIndexPath *indexPath = [_tableView1 indexPathForRowAtPoint:rootViewPoint];
NSLog(@"%@",indexPath);
スイフト2アップデート
タップされたボタンを確認する方法は次のとおりです
@IBAction func yourButton(sender: AnyObject) {
var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(position)
let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
UITableViewCell
print(indexPath?.row)
print("Tap tap tap tap")
}