uITableViewで、タッチした後にセルが選択されたままになることがあります。まれにしか発生しないため、問題を再現できません。
ヒントはありますか?多分それはtableViewの不適切なリリースと関係がありますか?
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
switch (row) {
case 0:
FruitViewController *fruitController = [FruitViewController alloc];
[fruitController retain];
[fruitController initWithNibName:@"FruitView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:fruitController animated:YES];
[fruitController release];
break;
case 1:
CerealsViewController *cerealsController = [CerealsViewController alloc];
[cerealsController retain];
[cerealsController initWithNibName:@"CerealsView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:cerealsController animated:YES];
[cerealsController release];
break;
default:
break;
}
}
この問題が発生している理由をお話しすることはできませんが、修正のためのいくつかの提案を以下に示します。
Apple HIGによると、スタックにプッシュされたばかりのビューコントローラーから戻るまで、選択は消えないはずです。コントローラーが単なるUITableViewControllerの場合、ビューに戻ったときに自動的に選択を解除する必要があります。そうでない場合は、追加
- (void) viewWillAppear:(BOOL)animated {
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:animated];
[super viewWillAppear:animated];
}
ビューコントローラのどこかに。
クリックしても別のビューに移動せず、実際に選択しても何もしない行がある場合、それらは選択可能であってはならないので、
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
また、行を選択してはならない場合はnil
を返します。
考えられる原因の1つは、UITableViewController
を拡張するコントローラーで-viewWillAppear:animated:
を呼び出さずに[super viewWillAppear]
をオーバーライドすることです。 [super viewWillAppear:animated]
メソッドの先頭に-viewWillAppear
を追加すると、問題が解決する場合があります。
「Ed Marty」の答えを拡張するために、見た目が良いと思ったので、代わりに「viewWillDisappear」メソッドに選択解除を追加することにしました。
これに加えて、(UITableViewControllerではなく)通常のUIViewControllerでUITableViewを使用していたため、tableView変数を使用できませんでした。これを克服するために、ビューコントローラーのヘッダーファイルにtableViewプロパティを追加しました(そしてXIBファイルに実際のテーブルビューをプロパティに接続しました)...
@property (nonatomic,retain) IBOutlet UITableView *tableView
...そしてビューコントローラの実装では、プロパティを配線し、次のように選択解除を実行しました。
@synthesize tableView
- (void) viewWillDisappear:(BOOL)animated {
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
[super viewWillDisappear:animated];
}
UITableViewControllerを使用している場合は、以下を使用できます。
self.clearsSelectionOnViewWillAppear = YES;
私の場合、didSelectRowAtIndexPathの最後にあるセルの選択を解除します。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Do smth here. segue ..etc
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO];
}
このメソッドをUITableViewCell
クラスで使用します
(void)setSelected:(BOOL)selected animated:(BOOL)animated {
// Just comment This line of code
// [super setSelected:selected animated:animated];
}
または、didSelectRowAtIndexPathメソッドでこのコードを試すこともできます
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//行が選択されたときに何らかの処理を行います
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
テーブルの管理方法を習得すると、この問題の解決には約2秒かかります。
セルが画面外にスクロールされるとすぐに、セルのフォーマットが失われます。テーブルは、他のセルを非表示にし、ユーザーがスクロールして戻ったときにセルを再作成することにより、メモリ使用量を最小限に抑えます。
テーブルデータの再読み込みなども、その時点で画面上のセルにのみ適用されます。つまり、cellForRowAtIndexPathは、ユーザーがボタンをクリックしたりビューコントローラを離れたりすることなく、同じセルを5回作成する可能性があります。したがって、すべてのフォーマットをリロードするように設定します。次のようなものをcellForRowAtIndexPathに追加します。
if arrayOf_SelectedCells.contains(indexPath) {
setup_Selected(cell)
//Where setup_Selected is a custom function to apply formatt
} else {
setup_Unselected(cell)
}