UITableViewCellが強調表示されたままになるのはなぜですか?


145

タッチした後、テーブルビューのセルが強調表示されたままになる原因は何ですか?セルをクリックすると、詳細ビ​​ューが押されてもセルが強調表示されたままになっていることがわかります。詳細ビューがポップされても、セルは引き続き強調表示されます。

回答:


262

では、セルの選択を解除didSelectRowAtIndexPathするために呼び出す必要がありますdeselectRowAtIndexPath

だから、あなたがあなたの中で他に何をしているとしても、didSelectRowAtIndexPathそれを呼び出すdeselectRowAtIndexPathだけです。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 // Do some stuff when the row is selected
 [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

11
deselectRowAtIndexPath行を選択して新しいビューを表示する場合は、viewDidAppearでを呼び出すことをお勧めします。
notnoop 2009

5
実際には、それを呼び出すのに適切な場所ではありません。本当に...テーブルでAppleアプリを使用してみてください(連絡先は良いものです)。新しい画面にプッシュした後、セルがまだ強調表示されています。選択が解除される前に短時間。理論的には私はあなたがviewDidAppear内のコードが必要とするべきではありませんので、それは、すぐに自分自身で選択解除持っている任意の余分な作業を行う必要はありませんと思う...
ケンドールHelmstetter Gelner

6
@ Kendall、@ 4thSpace:たぶん、私の最後のコメントは、私が誰を参照していたのか、そのことをお詫びすることで混乱したかもしれません。UITableViewControllerは、-deselectRowAtIndexPath:animated:そのtableViewプロパティのメソッドをから呼び出します-viewDidAppear。ただし、UIViewControllerサブクラスにテーブルビューがある場合は-deselectRowAtIndexPath:animated:-viewDidAppear自分で呼び出す必要があります。:)
ダニエル・タル

5
UITableViewControllerの私のサブクラスでは、それは実際に-viewWillAppear:それを壊したもののオーバーライドでした。[super viewWillAppear:animated]再び機能させるための呼び出しを追加します。
ベンチャレナー

5
3.2以降、UITableViewControllerclearsSelectionOnViewWillAppearプロパティがYES(デフォルト)に設定されてい[super viewWillAppear]て、呼び出されないようにしていない場合、自動選択解除動作が発生します。
2011年

62

それを行う最もクリーンな方法は、viewWillAppearです。

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // Unselect the selected row if any
    NSIndexPath*    selection = [self.tableView indexPathForSelectedRow];
    if (selection) {
        [self.tableView deselectRowAtIndexPath:selection animated:YES];
    }
}

これにより、コントローラーに戻ったときに、選択がフェードアウトするアニメーションが表示されます。

http://forums.macrumors.com/showthread.php?t=577677から取得

Swiftバージョン

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    // deselect the selected row if any
    let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
    if let selectedRowNotNill = selectedRow {
        tableView.deselectRow(at: selectedRowNotNill, animated: true)
    }
}

1
これは、UITableViewControllerを使用しない場合、ほとんどの人が望むと思うものです。+1
MikeB

3
iOS 7ではユーザーが「ドラッグ」できるようになっているので、人々は今何をしているのでしょうか。部分的にドラッグしてもアクションを完了しないと、viewWillAppearが発生します。ユーザーが実際に戻ると、行は選択されません。
Ben Packard

1
@BenPackardはviewDidAppear代わりにそれを呼び出します。
squarefrog 2014年

@Jessica indexPathForSelectedRow呼び出しはnilを返す可能性があるため、チェックする必要があります。ドキュメント状態はインデックスパスが無効な場合にインデックスパスは、選択された行、またはゼロの行とセクションのインデックスを識別する。
Gordonium

これは、ユーザーが戻って👌、完璧な取得した後の選択に到達することができますので、それはより多くのUIはフレンドリーだし、受け入れ答えとして発言すべきである
ヤヒヤAlshaar

20

サブクラス化しました-(void)viewWillAppear:(BOOL)animatedか?あなたは呼び出さないときに選択のUITableViewCellは解除しないであろう[super viewWillAppear:animated];、カスタム方法で。


19

Swiftユーザーの場合、これをコードに追加します。

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

Obj-Cの代わりにSwiftを除いて、それは非難の答えです。


1
それ自体が選択解除されるのではありませんか?
Honey

@Honeyおそらく、以前のバージョンのiOSで、またはビューが消えたときに、おそらくiOS 10(おそらくそれ以前でも)以降では、確かにそうではありません。
ジェイミーバーチ

9

Swift 3ソリューション

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
      tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}

7

UITableViewCellを使用している場合は、次の行をコメント化します

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{

 // [super setSelected:selected animated:animated];

}

お役に立てれば。


4

Swift 4で更新

いくつかの実験の後、これも以前の回答に基づいて、最良の動作は2つの方法で達成できるという結論に達しました(実際にはほとんど同じです)。

// First Solution: delegate of the table View
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: false)
}

// Second Solution: With the life cycle of the view.
override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)

    let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
    if let selectedRow = selectedRow {
        tableView.deselectRow(at: selectedRow, animated: false)
    }
}

私は最初の解決策を個人的に採用しています。tableViewに戻るときに小さなアニメーションが必要な場合の別の可能性は、次のようにすることですviewWillAppear

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    let selectedRow: IndexPath? = _view.tableView.indexPathForSelectedRow
    if let selectedRow = selectedRow {
        _view.tableView.deselectRow(at: selectedRow, animated: true)
    }
}

最後に、UITableViewControllerを使用している場合は、プロパティclearsSelectionOnViewWillAppearを利用することもできます。


3

Kendall Helmstetter Gelnerが彼のコメントで説明する動作を取得するには、おそらくdeselectRowAtIndexPathではなく、コントローラーのclearsSelectionOnViewWillAppearプロパティが必要です。おそらくこれは誤ってYESに設定されたのでしょうか?

新しいUITableViewControllerサブクラスについては、デフォルトのAppleテンプレートのコメントを参照してください。

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;
}

2

ドリルダウンアプリケーションでもこの問題が発生していました。別のViewControllerを押した後、VCと呼ぶビューコントローラーが戻った後、VCで選択されたセルが強調表示されたままになります。私のアプリでは、ドリルダウンの2番目のレベル(3レベルのうち)を処理するVCを作成しました。

私の場合の問題は、VCがUIViewController(TableViewを含むビューを含む)であったことです。代わりに、VCをUITableViewController(TableViewを含む)にしました。UITableViewControllerクラスは、プッシュから戻った後、テーブルセルのハイライト解除を自動的に処理します。「tableViewのdeselectRowAtIndexPathに関する問題」の投稿に対する2番目の回答は、この問題に対するより完全な回答です。

XViewで「ナビゲーションベースのアプリ」としてアプリを作成したとき、ルートビューコントローラーはサブテーブルUITableViewControllerにすでに作成されているため、ルートビューコントローラーでは問題は発生しませんでした。


1

これらのいずれもうまくいかない場合は、次の回避策を検討してください。

アンワインドセグエを使用して呼び出します。

@IBAction func unwind_ToTableVC (segue: UIStoryboardSegue) {
    if let index = tableView.indexPathForSelectedRow {
        tableView.deselectRowAtIndexPath(index, animated: true)
    }
}

なぜこれを行うのですか?主に、選択解除コードを適切なタイミングで実行できない場合。私はそれがviewWillAppearで機能しないことに問題があったので、巻き戻しがはるかにうまく機能しました。

手順:

  1. 巻き戻しセグエ(または上から貼り付け)を最初のVC(テーブルのあるVC)に書き込みます

  2. 2番目のVCに移動します。使用している[キャンセル] / [完了] / [その他]ボタンからControlキーを押しながらドラッグして、そのVCを閉じ、上部の[終了]アイコンにドラッグします。

  3. 手順1で作成した巻き戻しセグエを選択します

    幸運を。


これは、viewDidAppearが起動しない(つまり、子ビューがフォームシートとしてモーダルに表示され、画面全体をカバーしない)場合に最適なソリューションです。
pheedsta

1

私はCoreDataを使用しているので、私のために機能したコードは、Swiftのさまざまな答えからのアイデアの組み合わせでした:

override func viewDidAppear(_ animated: Bool) {
    if let testSelected = yourTable.indexPathForSelectedRow {
        yourTable.deselectRow(at: testSelected, animated: true)
    }
    super.viewDidAppear(true)
}

1
 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}

0

私は長い間同じ問題を抱えてきたので、他の誰かが苦労している場合に備えて:

あなたを見てください -tableView: cellForRowAtIndexPath:セルを作成しているか、「再利用識別子」を使用しているかを確認します。後者の場合は、IBのテーブルにその識別子のセルがあることを確認してください。再利用識別子を使用していない場合は、行ごとに新しいセルを作成するだけです。

これにより、テーブルに「フェードした選択された行」が表示されることが予想されます。


0

このメソッドをUITableViewCellクラスで使用します。

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

   // Just comment This line of code
   // [super setSelected:selected animated:animated];        
}

0

Swift 3の場合:viewDidDisappearで使用することをお勧めします

定義:-

    var selectedIndexPath = IndexPath()

viewDidDisappear:-

    override func viewDidDisappear(_ animated: Bool) {
    yourTableView.deselectRow(at: selectedIndexPath, animated: true)
}

didSelectRowAtIndexPath:-

    func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
    selectedIndexPath = indexPath
}

0

セルをタッチしてもハイライトされたままの場合は、UITabelViewメソッドを呼び出すことができます。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

`[tableView deselectRowAtIndexPath:indexPath animated:YES];`   

}

または、次の方法を使用して、要件に応じて変更できます。

//マーク:UITableViewDelegate

func tableView(tableView: UITableView, didHighlightRowAtIndexPath indexPath: NSIndexPath) {
  if let cell = tableView.cellForRowAtIndexPath(indexPath) {
     cell.backgroundColor = UIColor.greenColor()
  }
}

func tableView(tableView: UITableView, didUnhighlightRowAtIndexPath indexPath: NSIndexPath) {
  if let cell = tableView.cellForRowAtIndexPath(indexPath) {
     cell.backgroundColor = UIColor.blackColor()
  }
} 

0

Xcode 10、Swift 4

これと同じ問題があり、tableViewControllerの下部にあるviewWillAppearへの空の呼び出しを残していることを発見しました。空のオーバーライド関数を削除すると、tableViewビューに戻ったときに行が強調表示されたままになりません。

問題機能

override func viewWillAppear(_ animated: Bool) {
  // need to remove this function if not being used.
}

空の関数を削除すると問題が解決しました。


0

Swift 5ソリューション:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.