¿Por qué UITableViewCell permanece resaltado?

145

¿Qué haría que una celda de vista de tabla permanezca resaltada después de ser tocada? Hago clic en la celda y puedo ver que permanece resaltada mientras se empuja una vista detallada. Una vez que aparece la vista de detalle, la celda sigue resaltada.

4thSpace
fuente

Respuestas:

262

En su didSelectRowAtIndexPathnecesita llamar deselectRowAtIndexPathpara anular la selección de la celda.

Entonces, sea lo que sea que esté haciendo didSelectRowAtIndexPath, simplemente haga que llame deselectRowAtIndexPathtambién.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 // Do some stuff when the row is selected
 [tableView deselectRowAtIndexPath:indexPath animated:YES];
}
paulthenerd
fuente
11
Prefiero llamar deselectRowAtIndexPatha mi viewDidAppear, si selecciono la fila aparece una nueva vista.
notnoop 03 de
55
En realidad, ese no es el lugar correcto para llamarlo, realmente ... intente usar una aplicación de Apple con tablas (Contactos es una buena opción) y verá que después de salir a una nueva pantalla, al regresar, la celda aún está resaltada brevemente antes de ser deseleccionado. En teoría, creo que usted no tiene que hacer ningún trabajo extra para tener que anular la selección de inmediato por su propia cuenta, por lo que no se necesita el código en viewDidAppear ...
Kendall Helmstetter Gelner
66
@Kendall, @ 4thSpace: Quizás mi último comentario fue confuso sobre a quién me refería, disculpas por eso. UITableViewController llama al -deselectRowAtIndexPath:animated:método en su propiedad tableView desde -viewDidAppear. Sin embargo, si tiene una vista de tabla en una subclase de UIViewController, debe llamar -deselectRowAtIndexPath:animated:desde -viewDidAppearusted mismo. :)
Daniel Tull el
55
En mi subclase de UITableViewController, en realidad fue una anulación de -viewWillAppear:eso lo rompió. Agregar una llamada para [super viewWillAppear:animated]que funcione nuevamente.
Ben Challenor
55
Dado que 3.2, el comportamiento automático anulación de la selección se produce si su UITableViewController's clearsSelectionOnViewWillAppearpropiedad se establece en YES(que es el valor por defecto), y no se ha impedido [super viewWillAppear]de ser llamado.
Desfragmentado el
62

La forma más limpia de hacerlo es a la vista

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

De esta manera, tiene la animación de desvanecer la selección cuando regrese al controlador, como debería ser.

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

Versión rápida

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
fuente
1
Este es el que espero que la mayoría de la gente quiera si no usa un UITableViewController. +1
MikeB
3
Me pregunto qué está haciendo la gente ahora que iOS 7 permite al usuario 'arrastrar' hacia atrás. Arrastrando parcialmente pero luego no completando la acción activará viewWillAppear. Cuando el usuario regrese de verdad, la fila no será seleccionada.
Ben Packard
1
@BenPackard solo lo llama en su viewDidAppearlugar.
squarefrog
@Jessica La indexPathForSelectedRowllamada puede volver nula, por lo que debe verificarse. La documentación indica : Una ruta de índice que identifica los índices de fila y sección de la fila seleccionada, o nula si la ruta de índice no es válida.
Gordonium
Esto debería ser una respuesta aceptada, es más amigable con la interfaz de usuario para que el usuario pueda llegar a la selección después de regresar, perfecto 👌
Yahya Alshaar
20

¿Subclase -(void)viewWillAppear:(BOOL)animated? El UITableViewCell seleccionado no deseleccionará cuando no llame [super viewWillAppear:animated];a su método personalizado.

HansPinckaers
fuente
19

Para los usuarios de Swift, agregue esto a su código:

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

Es la respuesta de paulthenerd, excepto en Swift en lugar de Obj-C.

Rutger Huijsmans
fuente
1
¿no se deselecciona por sí solo, me refiero al momento en que lo sueltas?
Miel
@Honey Posiblemente así en una versión anterior de iOS, o al desaparecer la vista, pero ciertamente no ahora en iOS 10 (probablemente incluso antes) y superiores.
Jamie Birch
9

Solución Swift 3

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

Si está utilizando un UITableViewCell, comente la siguiente línea

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

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

}

Espero que esto ayude.

Shantanu
fuente
4

Actualizado con Swift 4

Después de algunos experimentos, también basados ​​en respuestas anteriores, tengo la conclusión de que el mejor comportamiento se puede lograr de 2 maneras: (casi idéntico en la práctica)

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

Personalmente, estoy adoptando la primera solución, porque es simplemente más conciso. Otra posibilidad, si necesita un poco de animación cuando regrese a su tableView, es 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 último, pero no menos importante, si está utilizando un UITableViewController, también puede aprovechar la propiedad clearsSelectionOnViewWillAppear .

Alessandro Francucci
fuente
3

Para obtener el comportamiento que Kendall Helmstetter Gelner describe en su comentario, es probable que no desee deseleccionarRowAtIndexPath sino la propiedad clearSsectionOnViewWillAppear en su controlador. ¿Quizás esto se estableció en SÍ por accidente?

Vea el comentario en la plantilla predeterminada de Apple para las nuevas subclases UITableViewController:

- (void)viewDidLoad
{
    [super viewDidLoad];

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

También recibí este problema para mi aplicación de desglose. Después de que un viewcontroller, que llamaré VC, regrese después de presionar otro ViewController, la celda seleccionada en VC permaneció resaltada. En mi aplicación, había creado VC para manejar el segundo nivel (de tres niveles) de mi desglose.

El problema en mi caso es que VC era un UIViewController (que contenía una Vista que contenía un TableView). En su lugar, hice de VC un UITableViewController (que contenía un TableView). La clase UITableViewController maneja automáticamente el resaltado de la celda de la tabla después de regresar de una inserción. La segunda respuesta a la publicación " Problema con deselectRowAtIndexPath en tableView " ofrece una respuesta más completa a este problema.

El problema no se produjo para el controlador de vista raíz porque cuando creé la aplicación como una "Aplicación basada en navegación" en XCode, el controlador de vista raíz resultante ya estaba hecho en la subclase UITableViewController.

stackoverflowuser2010
fuente
1

Si ninguno de estos funciona para usted, considere esta solución alternativa:

Use una secuencia de desconexión para llamar:

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

¿Por qué hacer esto? Principalmente si tiene problemas para ejecutar el código de deselección en el momento adecuado. Tuve problemas con que no funcionara en la vista Aparecerá así que el desenrollado funcionó mucho mejor.

Pasos:

  1. Escriba la secuencia de desenrollado (o pegue desde arriba) en su primer VC (el que está en la tabla)

  2. Ir a la segunda VC. Control-arrastre desde el botón Cancelar / Listo / Etc que está utilizando para descartar ese VC y arrastre hasta el ícono Salir en la parte superior.

  3. Seleccione el desenrollar segue que creó en el paso 1

    Buena suerte.

Dave G
fuente
Esta es la mejor solución para los momentos en que viewDidAppear no se activa (es decir, si la vista secundaria se presenta modalmente como una hoja de formulario y no cubre toda la pantalla).
pheedsta
1

Estoy usando CoreData, por lo que el código que funcionó para mí fue una combinación de ideas de varias respuestas, en Swift:

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

He tenido el mismo problema durante mucho tiempo, así que en caso de que alguien más esté luchando:

Eche un vistazo a su -tableView: cellForRowAtIndexPath:y vea si está creando celdas o está utilizando un 'identificador de reutilización'. Si es esto último, asegúrese de que su tabla en IB tenga una celda con ese identificador. Si no está utilizando un identificador de reutilización, simplemente cree una nueva celda para cada fila.

Esto debería dar a su tabla la 'fila seleccionada desvanecida' esperada al aparecer.

LearningAsIGo
fuente
0

Use este método en la clase UITableViewCell

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

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

Para Swift 3: preferiría que se use en viewDidDisappear

Definir:-

    var selectedIndexPath = IndexPath()

En viewDidDisappear: -

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

En didSelectRowAtIndexPath: -

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

si la celda permanece resaltada después de tocarla, puede llamar al método UITabelView,

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

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

}

O bien, puede usar el siguiente método y modificarlo según sus 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
fuente
0

Xcode 10, Swift 4

Tuve este mismo problema y descubrí que dejé una llamada vacía para verWillAppear en la parte inferior de mi tableViewController. Una vez que eliminé la función de anulación vacía, la fila ya no permaneció resaltada al regresar a la vista tableView.

problema func

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

eliminar la función vacía resolvió mi problema.

Robac
fuente
0

Solución Swift 5:

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