Por que o UITableViewCell permanece destacado?

145

O que faria com que uma célula de exibição de tabela permanecesse destacada após ser tocada? Clico na célula e posso ver que ela fica destacada quando uma exibição de detalhes é pressionada. Depois que a exibição de detalhes é exibida, a célula ainda é destacada.

4thSpace
fonte

Respostas:

262

No seu didSelectRowAtIndexPathvocê precisa ligar deselectRowAtIndexPathpara desmarcar a célula.

Então, o que quer que você esteja fazendo, didSelectRowAtIndexPathbasta chamar deselectRowAtIndexPath.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 // Do some stuff when the row is selected
 [tableView deselectRowAtIndexPath:indexPath animated:YES];
}
paulthenerd
fonte
11
Prefiro chamar o deselectRowAtIndexPathno meu viewDidAppear, se selecionar a linha abrir uma nova exibição.
Notnoop 03/12/2009
5
Na verdade, esse não é o lugar certo para chamá-lo, realmente ... tente usar um aplicativo da Apple com tabelas (os contatos são bons) e você verá, depois de sair para uma nova tela, ao retornar a célula ainda estará destacada brevemente antes de ser desmarcada. Em teoria, eu acho que você não tem que fazer qualquer trabalho extra para tê-lo desmarque imediatamente por conta própria, então o código em viewDidAppear não deve ser necessário ...
Kendall Helmstetter Gelner
6
@ Kendall, @ 4thSpace: Talvez meu último comentário tenha sido confuso sobre quem eu estava me referindo, desculpas por isso. UITableViewController chama o -deselectRowAtIndexPath:animated:método em sua propriedade tableView partir -viewDidAppear. No entanto, se você tiver uma exibição de tabela em uma subclasse UIViewController, deverá ligar -deselectRowAtIndexPath:animated:de -viewDidAppearsi mesmo. :)
Daniel Tull
5
Na minha subclasse de UITableViewController, foi realmente uma substituição -viewWillAppear:disso. Adicionando uma chamada para [super viewWillAppear:animated]fazê-la funcionar novamente.
Ben Challenor
5
Desde 3.2, o comportamento automático deselection ocorre se o UITableViewController's clearsSelectionOnViewWillAppearpropriedade é definida como YES(que é o padrão), e você não ter impedido [super viewWillAppear]de ser chamado.
defragged
62

A maneira mais limpa de fazer isso é no 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];
    }
}

Dessa forma, você tem a animação de diminuir a seleção ao retornar ao controlador, como deveria ser.

Retirado de http://forums.macrumors.com/showthread.php?t=577677

Versão 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)
    }
}
Danail
fonte
1
Esse é o que eu espero que a maioria das pessoas deseje se não usar um UITableViewController. 1
MikeB
3
Gostaria de saber o que as pessoas estão fazendo agora que o iOS 7 permite que o usuário 'arraste' de volta. Arrastar parcialmente, mas não concluir a ação, disparará o viewWillAppear. Quando o usuário retornar de verdade, a linha não será selecionada.
Ben Packard
1
@ BenPackard basta chamá-lo viewDidAppear.
22414 squarefrog
@ Jessica A indexPathForSelectedRowchamada pode retornar nula e deve ser verificada. A documentação declara : Um caminho de índice que identifica os índices de linha e seção da linha selecionada ou nulo se o caminho de índice for inválido.
Gordonium
isso deve observar como a resposta aceita, é mais UI amigável para que o usuário pode chegar a seleção depois de voltar, perfeito 👌
Yahya Alshaar
20

Você subclasse -(void)viewWillAppear:(BOOL)animated? O UITableViewCell selecionado não será desmarcado quando você não chamar [super viewWillAppear:animated];seu método personalizado.

HansPinckaers
fonte
19

Para os usuários do Swift, adicione isso ao seu código:

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

É a resposta de paulthenerd, exceto em Swift, em vez de Obj-C.

Rutger Huijsmans
fonte
1
não é desmarcada por si só, quero dizer no momento em que você solta?
Mel
@Honey Possivelmente na versão anterior do iOS, ou com a exibição desaparecendo, mas certamente não agora no iOS 10 (provavelmente ainda mais cedo) e acima.
Jamie Birch
9

Solução Swift 3

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

Se você estiver usando um UITableViewCell, comente a seguinte linha

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

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

}

Espero que isto ajude.

Shantanu
fonte
4

Atualizado com o Swift 4

Após algumas experiências, também baseadas em respostas anteriores, concluí que o melhor comportamento pode ser alcançado de duas maneiras: (quase idêntica na prática)

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

Pessoalmente, estou adotando a primeira solução, porque é simplesmente mais concisa. Outra possibilidade, se você precisar de um pouco de animação ao retornar ao tableView, é usar 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)
    }
}

Por fim, mas não menos importante, se você estiver usando um UITableViewController, também poderá tirar proveito da propriedade clearsSelectionOnViewWillAppear .

Alessandro Francucci
fonte
3

Para obter o comportamento que Kendall Helmstetter Gelner descreve em seu comentário, você provavelmente não deseja desmarcarRowAtIndexPath, mas sim a propriedade clearsSelectionOnViewWillAppear no seu controlador. Talvez isso tenha sido definido como SIM por acidente?

Veja o comentário no modelo padrão da Apple para novas subclasses UITableViewController:

- (void)viewDidLoad
{
    [super viewDidLoad];

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

Eu estava recebendo esse problema também no meu aplicativo de pesquisa detalhada. Depois que um viewcontroller, que chamarei de VC, retorna após pressionar outro ViewController, a célula selecionada no VC permanece destacada. No meu aplicativo, eu criei o VC para lidar com o segundo nível (de três níveis) do meu detalhamento.

O problema no meu caso é que o VC era um UIViewController (que continha uma View que continha um TableView). Em vez disso, fiz do VC um UITableViewController (que continha um TableView). A classe UITableViewController manipula automaticamente o realce da célula da tabela após retornar de um push. A segunda resposta à postagem " Problema com deselectRowAtIndexPath em tableView " fornece uma resposta mais completa para esse problema.

O problema não ocorreu no controlador de visualização raiz, porque quando eu criei o aplicativo como um "Aplicativo baseado em navegação" no XCode, o controlador de visualização raiz resultante já havia sido criado para subclassificar UITableViewController.

stackoverflowuser2010
fonte
1

Se nada disso funcionar para você, considere esta solução alternativa:

Use um desenrolar segue para chamar:

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

Por que fazer isso? Principalmente se você estiver com problemas para executar o código de desmarcação na hora certa. Eu tive problemas para não funcionar no viewWillAppear, então o desenrolamento funcionou muito melhor.

Passos:

  1. Escreva os seguimentos desenrolados (ou cole de cima) em seu 1º VC (aquele com a tabela)

  2. Vá para o 2º VC. Arraste com a tecla Control pressionada no botão Cancelar / Concluído / Etc que você está usando para dispensar o VC e arraste para o ícone Sair na parte superior.

  3. Selecione as etapas desenroladas que você criou na etapa 1

    Boa sorte.

Dave G
fonte
Esta é a melhor solução para os momentos em que o viewDidAppear não é acionado (ou seja, se o modo de exibição filho for apresentado modalmente como uma folha de formulário e não cobrir a tela inteira).
pheedsta
1

Estou usando o CoreData, então o código que funcionou para mim foi uma combinação de idéias de várias respostas, no Swift:

override func viewDidAppear(_ animated: Bool) {
    if let testSelected = yourTable.indexPathForSelectedRow {
        yourTable.deselectRow(at: testSelected, animated: true)
    }
    super.viewDidAppear(true)
}
Yewzr
fonte
1
 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
Mob
fonte
0

Eu tenho o mesmo problema há muito tempo, por isso, caso alguém esteja lutando:

Dê uma olhada no seu -tableView: cellForRowAtIndexPath: e veja se você está criando células ou usando um 'identificador de reutilização'. Nesse último caso, verifique se a sua tabela no IB possui uma célula com esse identificador. Se você não estiver usando um Identificador de reutilização, crie uma nova célula para cada linha.

Isso deve dar à sua tabela a 'linha selecionada fade selecionada' exibida.

LearningAsIGo
fonte
0

Use este método na classe UITableViewCell

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

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

Para Swift 3: eu preferiria usar no viewDidDisappear

Definir:-

    var selectedIndexPath = IndexPath()

Em viewDidDisappear: -

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

Em didSelectRowAtIndexPath: -

    func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
    selectedIndexPath = indexPath
}
Irshad Qureshi
fonte
0

se a célula permanecer destacada depois de tocá-la, você poderá chamar o método UITabelView,

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

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

}

Ou, você pode usar o seguinte método e modificá-lo de acordo com seus requisitos,

// MARK: 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()
  }
} 
Varsha Shivhare
fonte
0

Xcode 10, Swift 4

Eu tive esse mesmo problema e descobri que deixei uma chamada vazia para viewWillAppear na parte inferior do meu tableViewController. Depois de remover a função de substituição vazia, a linha não fica mais destacada ao retornar à visualização tableView.

função do problema

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

remover a função vazia resolveu meu problema.

Robac
fonte
0

Solução Swift 5:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
Zog
fonte