Como desmarcar uma célula UITableView selecionada?

212

Estou trabalhando em um projeto no qual tenho que pré-selecionar uma célula específica.

Posso pré-selecionar uma célula usando -willDisplayCell, mas não posso desmarcá-la quando o usuário clica em qualquer outra célula.

- (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];
}

Você pode ajudar?

RAM
fonte
11
Esta pergunta precisa ter uma resposta aceita
Titouan de Bailleul

Respostas:

407

use este código

- (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)
}
Saikiran K
fonte
1
Existe um didDeselectRowAtIndexPath a ser usado para desmarcar o anterior.
huggie
3
Gosto de pensar que eu não posso upvote este post porque iria causar um estouro de inteiro :)
Milo
oi @ram, você precisa selecionar uma resposta sobre esta questão
Fattie
4
Eu não entendo ... esse código nunca permitirá que nada seja selecionado.
C. Tewalt
@matrixugly está certo. É mais apropriado fazer isso por dentro willSelectRowAt:. Veja uma resposta mais completa aqui: stackoverflow.com/questions/12693402/…
HuaTham
117

Use o método a seguir nos delegados da exibição de tabela didSelectRowAtIndexpath(ou de qualquer lugar)

[myTable deselectRowAtIndexPath:[myTable indexPathForSelectedRow] animated:YES];
Shamitha
fonte
2
Vale a pena notar que indexPathForSelectedRowé um método e não uma propriedade.
FreeAsInBeer
Doce! Não sabia [myTable indexPathForSelectedRow]. Eu estava percorrendo as células antes. Obrigado!
precisa saber é o seguinte
@FreeAsInBeer Essa distinção é importante de alguma forma? Os acessadores de propriedades são métodos.
devios1
@chaiguy Tudo bem se você não se importa que seus colegas o considerem mal .
FreeAsInBeer 04/07
1
@Supertecnoboff Não há diferença no desempenho entre as duas variações.
FreeAsInBeer
38

Tente o seguinte:

for (NSIndexPath *indexPath in tableView.indexPathsForSelectedRows) {
    [tableView deselectRowAtIndexPath:indexPath animated:NO];
}
ikosdroid
fonte
1
Bom trabalho ... Eu acho que 'index' na 2ª linha deve ser indexPath
El Tomato
isso não é suportado no iOS 11 Swift 4
Boris Nikolic
30

Pode ser útil fazer uma extensão no Swift para isso.

Swift 4 e Swift 5:

Extensão Swift (por exemplo, em um arquivo UITableViewExtension.swift):

import UIKit

extension UITableView {

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

}

Use, por exemplo:

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

    self.tableView.deselectSelectedRow(animated: true)
}
Thomas Neuteboom
fonte
1
Na minha opinião, essa resposta é melhor porque colocar a desolação no viewWillAppear()método ajuda o usuário a entender de onde ele volta.
MonsieurDart
o perfeito como eu precisava
Patel Jigar
28

Por favor, verifique com o método delegado se está correto ou não. Por exemplo;

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

para

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
jfalexvijay
fonte
Estava chamando o método errado esse tempo todo, arghh !! Obrigado!
Damir Kotoric
1
oh cara .... sangrenta autocompletar !!! Levei várias horas para descobrir !!! OMG ... eu quero te beijar!
George Asda
22

Swift 4:

tableView.deselectRow(at: indexPath, animated: true)
Andrea.Ferrando
fonte
Não precisa ser declarado não opcional, mas isso está correto.
Michael
16

Esta é uma solução para o Swift 4

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

basta adicionar

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

Ele funciona como um encanto

exemplo:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
//some code
}
tBug
fonte
até que você adicione a seleção sobre a edição em sua tableview, será impossível selecionar qualquer célula porque vai desmarcá-lo quando você terminar de selecionar o :)
Mehdi Chennoufi
Esta é certamente a abordagem correta, quando você não está editando, quando está "tocando em uma linha para fazer alguma coisa"
Fattie
11

Além de definir a célula como selecionada, você também precisa informar ao tableView que a célula está selecionada. Adicione uma chamada ao -tableView:selectRowAtIndexPath:animated:scrollPosition:seu willDisplayCell:método: e você poderá desmarcá-la normalmente.

- (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];   
    } 
}

Certifique-se de usar UITableViewScrollPositionNone para evitar um comportamento de rolagem estranho.

Drew C
fonte
1
Absolutamente correto. Eu acho que [cell setSelected:YES]poderia ser omitida: selectRowAtIndexPathvai cuidar da célula selectedde estado
spassas
Essa resposta funciona para o UITableView com várias seleções. Afirmativo.
Danny Bravo
6

Isso deve funcionar:

[tableView deselectRowAtIndexPath:indexpath1 animated:NO];

Apenas verifique se materialTable e tableView estão apontando para o mesmo objeto.

Os materiais estão conectados ao tableView no Interface Builder?

Jordânia
fonte
Eu testei com NO, mas isso também não resolve o meu problema. mas eu corrigi esse problema com outra maneira, como Dados recarregados, sempre que o delegado selecionado selecionava.
Ram
6

Com base na solução saikirans, escrevi isso, o que me ajudou. No arquivo .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];

}

E no arquivo de cabeçalho:

@property (retain, nonatomic) NSIndexPath* selectedRowIndex;

Também não sou muito experiente, então verifique se há vazamentos de memória etc.

Yunus Nedim Mehel
fonte
6

Se você deseja selecionar qualquer célula da tabela com o primeiro clique e desmarcar com o segundo, use este código:

- (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;
    }
}
CHiP-love-NY
fonte
5

Swift 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
    }
}
Serguei Vinnitskii
fonte
2
Isso funcionou para mim em Swift 3. Apenas teve que adicionar self.tableView(tableView, didDeselectRowAt: indexPath)depois tableView.deselectRow...porque não foi chamado automaticamente
elysch
4

Swift 2.0:

tableView.deselectRowAtIndexPath(indexPath, animated: true)
Anit Kumar
fonte
3

tente isso

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
EnasAZ
fonte
tente explicar sua resposta, caso contrário, deve ser um comentário.
Hugo Dozois
3
NSIndexPath * index = [self.menuTableView indexPathForSelectedRow];
[self.menuTableView deselectRowAtIndexPath:index animated:NO];

coloque esse código de acordo com o seu código e sua célula será desmarcada.

rahulchona
fonte
3

Você pode tentar isso?

- (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];
    }
}

Funcionou para mim.

Dattatraya Anarase
fonte
2

Swift 3.0:

Seguindo a seção de conformidade do protocolo do guia de estilo ray wenderlich swift , para manter os métodos relacionados agrupados, coloque esta extensão abaixo da classe do controlador de exibição da seguinte maneira:

// 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)
    }
}
ronatório
fonte
1

Rápido

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)

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

Swift 3

Também me deparei com isso - quando você navega ou volta à exibição da tabela, geralmente não desmarca a linha selecionada anteriormente para você. Coloquei esse código no controlador de exibição de tabela e funciona bem:

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

Swift 3/4

No ViewController:

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

Na célula personalizada:

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

swift 3.0

    tableView.deselectRow(at: indexPath, animated: true)
Marcelo Gracietti
fonte
0

Para desmarcar (DidDeselectRowAt) disparar quando clicado pela primeira vez devido a dados pré-carregados; você precisa informar ao tableView que a linha já está selecionada para começar, para que um clique inicial desmarque a linha:

// 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)

    }
}
Arkelyan
fonte
0

O que eu descobri é que, além de definir a célula como selecionada , você deve informar a exibição da tabela para selecionar a linha no caminho do índice fornecido.

// 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)
    }
}
David Para
fonte