2009-12-01 15 views
23

Escribo cliente de jabber personalizado en iphone.guardar la fila seleccionada en UITableView después de reloadData

Yo uso xmppframework como motor.

Y tengo UITableViewController con NSMutableArray para la lista de contactos representados.

Cuando recibo (o alguien lo cambia el contenido) la lista (también conocida como lista de contactos) quiero cambiar los elementos de UITableView (agregar/eliminar/modificar). Así que si el trabajo del usuario con ListView en el momento en que la lista de actualizaciones por

[items addObject:newItem]; 
[self.tableView reloadData]; 

usuario perdieron elemento de selección actual.

Por lo tanto, mi pregunta es cómo guardar (si es posible, me refiero si se da el elemento seleccionado no eliminado) elemento de selección actual después de reloadData?

Thx.

Respuesta

-5

Parece que no está utilizando un 'modelo' para los datos, sino que simplemente actualiza la 'vista' (interfaz de usuario), y probablemente sea un mal diseño.

reloadData debe hacer que la vista se actualice con los datos del modelo, que debe contener la información más reciente que se mostrará.

búsqueda de recursos en el 'modelo patrón de controlador de vista'

+0

sin , Realmente uso NSMuttableArray para delegar el origen de datos de tabla y agregar/eliminar datos en este conjunto, pero para hacer que refresh tableViewView llame al método reloadData después de modificar el conjunto. ¿Estoy en lo cierto? Pero después de esta tabla, se perdió la selección. – vinnitu

+0

Es difícil ayudarle sin ver su código, pero los métodos de tableView deben crear la tabla a partir de la fuente de datos, por lo tanto, simplemente actualice el modelo de datos y fire reloadData. – Mobs

3

La solución consiste en utilizar reloadSections: en lugar de reloadData. Por algún motivo, reloadData elimina la selección actual.

+1

Esto no funciona. – ZaBlanc

+0

me funciona a la perfección, gracias :) –

+5

Tengo que corregirme. Funciona perfectamente en iOS 4.0 pero no en 4.2 y superior –

62

La manera más fácil es algo como esto:

NSIndexPath *ipath = [self.tableView indexPathForSelectedRow]; 
[self.tableView reloadData]; 
[self.tableView selectRowAtIndexPath:ipath animated:NO scrollPosition:UITableViewScrollPositionNone]; 
+0

[setSelección de celda: YES] no funciona correctamente. Así que utilicé este método que funciona bien – Vassily

+0

Encontrado que no debe poner esto en un [self.tableView beginUpdates]/[self.tableView endUpdates]. – ChrisP

+1

Bravo, salvaste mi día ... Happy Coding. – josh

1

Esto funciona para mí:

NSIndexPath *indexPath = [table indexPathForSelectedRow]; 
[table reloadData]; 
double delayInSeconds = 0.01; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    [self.table selectRowAtIndexPath:indexPath animated:YES 
           scrollPosition:UITableViewScrollPositionNone]; 
}); 

El truco es hacer que se ejecute más tarde selectRowAtIndexpath un poco. El código anterior es una plantilla de Xcode que puede seleccionar al comenzar a escribir dispatch_after.

+0

¿Alguna idea de cuánto tiempo debemos demorarla? En mi caso, con iOS 8, en el simulador, este error nunca ocurrió, sospecho porque el simulador era mucho más rápido que el dispositivo real. Pero cuando lo pruebo en el iPhone, configuro la demora en 0.15 segundos y sigo recibiendo la excepción. – Kurotsuki

20

Añadiendo un poco a la respuesta de Marco:

En primer lugar, si usted está utilizando selección múltiple, puede añadir este método para su ViewController y llamarlo cada vez que necesite llamar a [tableView reloadData]:

- (void)reloadTableView 
{ 
    NSArray *indexPaths = [self.tableView indexPathsForSelectedRows]; 
    [self.tableView reloadData]; 
    for (NSIndexPath *path in indexPaths) { 
     [self.tableView selectRowAtIndexPath:path animated:NO scrollPosition:UITableViewScrollPositionNone]; 
    } 
} 

En segundo lugar, si está en un UITableViewController y desea conservar la selección después de que TableView aparezca, hay una función en UITableViewController: clearsSelectionOnViewWillAppear que puede activarse o desactivarse.

Ver aquí: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewController_Class/Reference/Reference.html

+0

tu hermano rock, buena solución, salvó el día – Aragunz

0

Esta es una solución para el caso si usted quiere hacer actualizaciones de la tabla y mantener la selección:

NSIndexPath* pathToSelect = [self.tableView indexPathForSelectedRow]; 
    if (pathToSelect && newRows) { 
     int row = pathToSelect.row; 
     for (NSIndexPath* path in newRows) { 
      if (path.section == pathToSelect.section && path.row <= pathToSelect.row) { 
       row++; 
      } 
     } 
     pathToSelect = [NSIndexPath indexPathForRow:row inSection:pathToSelect.section]; 
    } 

    [self.tableView beginUpdates]; 
    if (reloadRows) [self.tableView reloadRowsAtIndexPaths:reloadRows withRowAnimation:UITableViewRowAnimationFade]; 
    if (newSections) [self.tableView insertSections:newSections withRowAnimation:UITableViewRowAnimationFade]; 
    if (newRows) [self.tableView insertRowsAtIndexPaths:newRows withRowAnimation:UITableViewRowAnimationFade]; 
    [self.tableView endUpdates]; 

    if (pathToSelect) { 
     [self.tableView selectRowAtIndexPath:pathToSelect animated:NO scrollPosition:UITableViewScrollPositionNone]; 
    } 
4

Adición de un retraso que no funcionó para mí (probado en iOS 8.4 e iOS 9). Lo que funcionó fue agregar una llamada al -layoutIfNeeded en la celda seleccionada, después de llamar al -selectRowAtIndexPath:animated:scrollPosition:.

NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow]; 
[self.tableView reloadData]; 
[self.tableView selectRowAtIndexPath:selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; 
[[self.tableView cellForRowAtIndexPath:selectedIndexPath] layoutIfNeeded]; 
+0

Un retraso huele poco fiable, esto funcionó para mí. Si lo está haciendo desde 'viewWillAppear', realice la reselección antes de llamar a' super'. – Sebastian

0

En iOS 9.3 y 2.x Swift, simplemente tenía que llamar a la función en el hilo principal :)

self.tableView?.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None) 
0

SWIFT 3:

self.collectionView.reloadData() 
self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: []) 
Cuestiones relacionadas