0

テーブル ビューから行を削除する際に問題が発生しました。行のボタンが押されたときに呼び出されるコードを次に示します。tag パラメーターを使用して、どの行を扱っているかを教えてくれました。これが、最後に reloadTableView を呼び出して、すべてのタグを再適用する理由です。表示されている行を更新すると、クラッシュが発生しました。それで、私はここで何か間違ったことをしているに違いありませんか?

- (void) deleteLineItem:(id)sender
{
    UIButton *deleteBtn = sender; // Need to get tag (which was set to table row)
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(deleteBtn.tag/3) inSection:0];
    NSLog(@"Removed entry at %d, with tag %d", indexPath.row, deleteBtn.tag);
    [self.productItems removeObjectAtIndex:indexPath.row];

    [self.tableview beginUpdates];
    [self.tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
    [self.tableview endUpdates];

    // Hack to keep table animation ok as we have to do it after the row delete above
    [self performSelector:@selector(reloadTableview) withObject:nil afterDelay:0.35];
}

この場合、テーブルに 2 つの行があります。データソースは次のとおりです。

Printing description of self->productItems:
(__NSArrayM *) productItems = 0x084fa3b0 @"2 objects"

indexPath は次のとおりです。

Printing description of indexPath:
<NSIndexPath 0x1069bff0> 2 indexes [0, 1]

endUpdates メソッドが呼び出されると、コンソールで次のクラッシュが発生します

2012-10-17 17:04:33.424 myAppname[5782:15203] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(0x1bf0022 0x1918cd6 0x1bdcd88 0xa5553 0xa576b 0x925420 0x963284 0x9633d0 0x925219 0x8fd4f2 0x8fa4c3 0x9050b7 0x9050e5 0xa6ae1 0x1bf1e99 0x87814e 0x8780e6 0x91eade 0x91efa7 0x91e266 0xb39a1a 0x1bc499e 0x1b5b640 0x1b274c6 0x1b26d84 0x1b26c9b 0x25007d8 0x250088a 0x875626 0x1f2ba 0x2ba5)
terminate called throwing an exception(lldb)

なぜ問題を引き起こしているのかわかりません。

4

3 に答える 3

1

コードはあまり堅牢ではないようです。deleteBtn.tagセルが 1 つしかない悪い値 (より正確には 3 から 5 の間) を設定したようです。推測です。

私が使用するこのようなタスクのより堅牢な手法は、UITableViewCellサブクラスに IBAction を実装し、委譲とセル自体を引数として要求をコントローラーに伝達することです。コントローラーで、次の方法で indexPath を取得します

[self.tableView indexPathForCell:cell];

このようにして、そのようなハッキングを回避します。

于 2012-10-17T18:02:33.737 に答える
0

@ilimiacsはい、それは正しいです。それは良い方法です。しかし、セルは複雑で、2 つのボタンと 2 つのテキスト フィールドがあります。

タグを使用して、行を取得するために 3 で割って、どのセルにいるのかを判断しました (セルごとに 3 つのタグ、0、1、2 を使用)。タグ 3 は行 1 になるため、3 で割ります。

しかし、私はそこにセルクラスを持っており、委任でそれを行うことの実現可能性を見ていきます.ボタンにとっては簡単ですが、フォームであるためテキストフィールドにとってはそれほど簡単ではありません.あるフィールドから次のフィールドへ、タグがこれを簡単にしました。

とにかく、この答えは確かに役に立ち、おそらく完全な解決策になるので、この答えを受け入れます。

于 2012-10-18T09:13:37.267 に答える
0

@ilmiacs 提案ありがとうございます。あなたが言ったように実装し、タグを取り除き、すべてが動作するようになりました。再実装するのは少し面倒でしたが、ハックが減り、より読みやすいコードになりました。

残りの行のすべてのタグ値を再計算する代わりに、最初の行を更新するだけで済みました。削除ボタンが最後に残っている場合は、最初の行から削除する必要があります... ご覧のとおり、もう少し簡単になりました。

- (void) deleteCell:(NSIndexPath *)indexPath
{
    NSIndexPath *firstRow = [NSIndexPath indexPathForRow:0 inSection:0];
    [self.productItems removeObjectAtIndex:indexPath.row];

    [self.tableview beginUpdates];
    [self.tableview deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
    [self.tableview reloadRowsAtIndexPaths:[NSArray arrayWithObject:firstRow] withRowAnimation:UITableViewRowAnimationNone];
    [self.tableview endUpdates];
}

ありがとうございました...

于 2012-10-18T18:32:04.690 に答える