選択したUITableViewセルの選択を解除する方法は?


212

特定のセルを事前選択する必要があるプロジェクトに取り組んでいます。

を使用してセルを事前選択でき-willDisplayCellますが、ユーザーが他のセルをクリックしたときに選択を解除することはできません。

- (void)tableView:(UITableView*)tableView 
        willDisplayCell:(UITableViewCell*)cell
        forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        [cell setSelected:YES];    
    } 
}

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

    AppDelegate_iPad *appDelegte = 
      (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;
    [materialTable deselectRowAtIndexPath:indexpath1 animated:NO];
}

手伝ってくれますか?


11
この質問には承認された回答が必要です
Titouan de Bailleul

回答:


407

このコードを使用

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
 {
    //Change the selected background view of the cell.
     [tableView deselectRowAtIndexPath:indexPath animated:YES];
 }

Swift 3.0:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //Change the selected background view of the cell.
    tableView.deselectRow(at: indexPath, animated: true)
}

1
前のものを選択解除するために使用するdidDeselectRowAtIndexPathがあります。
ハギー14

3
整数のオーバーフローが発生するため、この投稿に賛成できないと思います:)
Milo

こんにちは@ram、この質問の答えを選択する必要があります
Fattie

4
わかりません...このコードでは、何も選択されません。
C. Tewalt 2016年

@matrixuglyは正しいです。内部でこれを行うのがより適切willSelectRowAt:です。:ここでは、より完全な答えを参照してくださいstackoverflow.com/questions/12693402/...
HuaTham

117

テーブルビューのデリゲートでdidSelectRowAtIndexpath(またはどこからでも)次のメソッドを使用します。

[myTable deselectRowAtIndexPath:[myTable indexPathForSelectedRow] animated:YES];

2
これindexPathForSelectedRowはメソッドであり、プロパティではないことに注意してください。
FreeAsInBeer

甘い!について知りませんでした[myTable indexPathForSelectedRow]。以前は細胞をループしていた。ありがとう!
guptron 2013

@FreeAsInBeerこの区別はどういうわけか重要ですか?プロパティアクセサーはメソッドです。
devios1 2013

@chaiguy同僚があなたを邪悪だと思っても構わないなら、それでいい。
FreeAsInBeer 2013

1
@Supertecnoboff 2つのバリエーションのパフォーマンスに違いはありません。
FreeAsInBeer

38

これを試して:

for (NSIndexPath *indexPath in tableView.indexPathsForSelectedRows) {
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}

1
よくできました... 2行目の 'index'はindexPathにする必要があると思います
El Tomato

これはiOS 11 Swift 4ではサポートされていません
Boris Nikolic

30

これには、Swiftで拡張機能を作成すると便利な場合があります。

Swift 4およびSwift 5:

Swift拡張(例えば、UITableViewExtension.swiftファイル内):

import UIKit

extension UITableView {

    func deselectSelectedRow(animated: Bool)
    {
        if let indexPathForSelectedRow = self.indexPathForSelectedRow {
            self.deselectRow(at: indexPathForSelectedRow, animated: animated)
        }
    }

}

例:

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

    self.tableView.deselectSelectedRow(animated: true)
}

1
私の意見では、viewWillAppear()メソッドに荒廃を入れることは、ユーザーがどこから戻ってきたかをユーザーが理解するのに役立つため、この答えの方が優れています。
MonsieurDart 2017年

必要に応じて最適なもの
Patel Jigar 2017年

28

正しいかどうかはデリゲートメソッドで確認してください。例えば;

-(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

ために

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

この間、間違ったメソッドを呼び出していました、arghh !! ありがとうございました!
Damir Kotoric 2014

1
ああ男...血のオートコンプリート!!! それを理解するのに数時間かかりました!!! OMG ...キスしたい!
ジョージアスダ2016年


16

これはSwift 4のソリューションです

 in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

追加するだけ

tableView.deselectRow(at: indexPath, animated: true)

それは魅力のように機能します

例:

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

テーブルビューで編集時に選択を追加するまで、選択を完了するとセルの選択が解除されるため、セルを選択することはできません:)
Mehdi Chennoufi '27 / 08/27

これは、あなたがしている「何かをする行をタップ」するときに、編集していないとき、確かに正しいアプローチである
Fattie

11

セルを選択済みとして設定することに加えて、セルが選択されていることをtableViewに通知する必要もあります。メソッドへの呼び出しを追加-tableView:selectRowAtIndexPath:animated:scrollPosition:しますwillDisplayCell:。通常どおり、選択を解除できます。

- (void)tableView:(UITableView*)tableView 
  willDisplayCell:(UITableViewCell*)cell
forRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    AppDelegate_iPad *appDelegte = (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];

    if ([appDelegte.indexPathDelegate row] == [indexPath row])
    {
        // SELECT CELL
        [cell setSelected:YES]; 
        // TELL TABLEVIEW THAT ROW IS SELECTED
        [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];   
    } 
}

奇妙なスクロール動作を避けるために、UITableViewScrollPositionNoneを必ず使用してください。


1
正解です。[cell setSelected:YES]省略できると思います。selectRowAtIndexPathセルのselected状態を処理します
spassas

この回答は、複数の選択があるUITableViewで機能します。いいぞ。
Danny Bravo

6

これはうまくいくはずです:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

materialTableとtableViewが同じオブジェクトを指していることを確認してください。

マテリアルはInterface BuilderのtableViewに接続されていますか?


私はNOでテストしましたが、それでも私の問題は解決しません。しかし、didselectデリゲートが発生したときにデータを再読み込みする別の方法でこの問題を修正しました。
Ram

6

saikiransソリューションに基づいて、私はこれを書いて、助けになりました。.mファイル:

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

    if(selectedRowIndex && indexPath.row == selectedRowIndex.row) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        selectedRowIndex = nil;

    }

    else {  self.selectedRowIndex = [indexPath retain];   }

    [tableView beginUpdates];
    [tableView endUpdates];

}

そしてヘッダーファイル上で:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

私もあまり経験がないので、メモリリークなどをダブルチェックします。


6

最初のクリックでテーブルセルを選択し、2番目のクリックで選択解除する場合は、次のコードを使用する必要があります。

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

    if (self.selectedIndexPath && 
        [indexPath compare:self.selectedIndexPath] == NSOrderedSame) {

        [tableView deselectRowAtIndexPath:indexPath animated:YES];
         self.selectedIndexPath = nil;
    } 
    else {
        self.selectedIndexPath = indexPath;
    }
}

5

スウィフト4:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    let cell = tableView.cellForRow(at: indexPath)
    if cell?.isSelected == true { // check if cell has been previously selected
        tableView.deselectRow(at: indexPath, animated: true)
        return nil
    } else {
        return indexPath
    }
}

2
スウィフト3.だけで私のために働いていたこれは、追加する必要がありましたself.tableView(tableView, didDeselectRowAt: indexPath)後にtableView.deselectRow...、それが自動的に呼び出されなかったため
elysch


3

これを試して

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];

あなたの答えを説明してみてください、そうでなければコメントでなければなりません。
Hugo Dozois、2013

3
NSIndexPath * index = [self.menuTableView indexPathForSelectedRow];
[self.menuTableView deselectRowAtIndexPath:index animated:NO];

コードに従ってこのコードを配置すると、セルの選択が解除されます。


3

試して頂けますか?

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

    AppDelegate_iPad *appDelegte = 
    (AppDelegate_iPad *)[[UIApplication sharedApplication] delegate];
    NSIndexPath *indexpath1 = appDelegte.indexPathDelegate;
    appDelegte.indexPathDelegate = indexPath;

    UITableViewCell *prevSelectedCell = [tableView cellForRowAtIndexPath: indexpath1];
    if([prevSelectedCell isSelected]){
       [prevSelectedCell setSelected:NO];
    }
}

それは私のために働いた。


2

Swift 3.0:

ray wenderlichのSwiftスタイルガイドプロトコル準拠セクションに従って、関連するメソッドをグループ化しておくには、この拡張機能をビューコントローラークラスの下に次のように配置します。

// your view controller
class MyViewcontroller: UIViewController {
  // class stuff here
}

// MARK: - UITableViewDelegate
extension MyViewcontroller: UITableViewDelegate {
      // use the UITableViewDelegate method tableView(_:didSelectRowAt:)
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        // your code when user select row at indexPath

        // at the end use deselectRow
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

1

迅速

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    // your code

    // your code

    // and use deselect row to end line of this function

    self.tableView.deselectRowAtIndexPath(indexPath, animated: true)

}

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

1

スウィフト3

私もこれに遭遇しました-テーブルビューに移動または巻き戻した場合、通常は以前に選択した行の選択を解除しません。このコードをテーブルビューコントローラーに配置すると、うまく機能します。

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

1

スイフト3/4

ViewControllerで:

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

カスタムセル:

override func awakeFromNib() {
    super.awakeFromNib()
    selectionStyle = .none
}


0

データがプリロードされているため、最初にクリックされたときに選択解除(DidDeselectRowAt)が発生するようにします。最初に行がすでに選択されていることをtableViewに通知して、最初のクリックで行の選択を解除する必要があります。

// Swift 3:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if tableView[indexPath.row] == "data value"

        tableView.selectRow(at: indexPath, animated: false, scrollPosition: UITableViewScrollPosition.none)

    }
}

0

私が見つけたのは、セルをselectedとして設定することに加えて、テーブルビューに特定のインデックスパスで行を選択するように通知する必要があるということです。

// Swift 3+  

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if appDelegate.indexPathDelegate.row == indexPath.row {
        self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
        cell.setSelected(true, animated: true)
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.