¿Cuál es el significado del post "sin ruta de índice para celda de tabla que se está reutilizando" en iOS 6/7?

Desde que comencé a comstackr mi aplicación con iOS 6 (y desde iOS 7 también), empecé a ver este post. Sé que la forma en que UITableViews se dedica a la administración de células es diferente en iOS 6, pero no he necesitado modificar mi código para que siga funcionando. Pero me preocupa que este post apunte a algún problema potencial que aún no veo. ¿Alguien puede arrojar algo de luz?

Empecé a mostrar este error en el logging desde iOS 7 beta 5 en adelante, incluso en iOS 7 GM / Release build, aunque nunca lo he tenido en mi aplicación iOS 6 o en iOS 7 beta anteriores. Después de muchos experimentos encontré la causa:

Estuve usando objects UITableViewCell para las vistas de mi encabezado de sección y volviéndolos en tableView:viewForHeaderInSection: Esto parece ser una práctica común, especialmente desde iOS 5 cuando se hizo fácil diseñar una vista de encabezado de sección como una celda de vista de tabla de prototipo en una StoryBoard con Interface Builder.

Cuando cambié mi aplicación para usar solo subclasss UIView regulares para las vistas de mi encabezado de sección, los errores desaparecieron y, lo que es más importante, ¡mi vista de tabla se detuvo random eliminando encabezados de sección!

Parece que (desde iOS 7 beta 5) UITableView está manteniendo internamente un mapeo de todos los objects UITableViewCell en su jerarquía de vista y sus respectivas routes de índice. Dado que un encabezado de sección (o un encabezado de vista de tabla del pie de página) no tiene una ruta de índice, si usa un object UITableViewCell para estas vistas, la vista de tabla se confundirá cuando encuentre un UITableViewCell para el que no tenga una ruta de acceso de índice, lo que resulta en el error "sin ruta de índice para la celda de tabla que se está reutilizando" y, si tiene mala suerte, muestra fallas en su vista de tabla:

ACTUALIZACIÓN : si tiene acceso a los foros de Apple Dev, aquí está el hilo sobre el tema (que comencé): https://devforums.apple.com/message/882042#882042

Tal como se sugiere en ese hilo, si no desea volver a factorizar demasiado, puede crear un contenedor UIView alnetworkingedor de UITableViewCell y devolverlo como vista del encabezado de sección.

 UIView *view = [[UIView alloc] initWithFrame:[cell frame]]; [view addSubview:cell]; return view; 

Sin embargo, UIView count que este enfoque " UIView " de "contenedor" no funcionará bien con AutoLayout y la rotation del dispositivo, por lo que sugiero que utilice una subclass UIView para celdas de encabezado y pie de página, no una subclass UITableViewCell como se explica en la parte principal de la respuesta.

Devolvería la vista de contenido de UITableViewCell en lugar de crear una envoltura … teniendo en count la restricción-jabble fija en el storybord

 return cell.contentView; 

Tuve el mismo problema y me costó unas cuantas horas perseguir el problema. Resulta que estaba llamando [textField becomeFirstResponder] al configurar celdas (aquí el textField era parte de una tabla de celdas personalizada); [textField becomeFirstResponder] en los turnos de posts keyboardWillShow notificación que a su vez provocó que la vista de tabla se cargue prematuramente provocando así el infame post " sin ruta de índice para la celda de tabla que se está reutilizando ". Una vez que eliminé esa llamada, el problema desapareció.

Además de la respuesta aceptada (mluisbrown), necesitaba agregar un Masking autorizante a la celda del encabezado, ya que el mío contenía una label de varias líneas, es decir

 UIView *view = [[UIView alloc] initWithFrame:[cell frame]]; cell.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; [view addSubview:cell]; return view; 

Este es un error interno de UIKit, como se menciona en los foros de desarrollo de Apple. Supuestamente se corrigió en versiones más nuevas de xcode, aunque no pude encontrar información sobre qué versión soluciona esto.

Como una adición a mi publicación anterior (en la que mencioné que esto aparentemente era un error con UIKit), pude encontrar una solución para mi caso particular (en el que el post estaba relacionado con algunas fallas de visualización extrañas en la tabla).

Al parecer, mi celda personalizada está anulada -(void)setEditing:animated: demasiado en volver.

Mi código anterior fue:

 - (void)setEditing:(BOOL)editing animated:(BOOL)animated { [super setEditing:editing animated:animated]; [self someAdditionalCode]; } 

Pude solucionarlo cambiándolo a:

 - (void)setEditing:(BOOL)editing animated:(BOOL)animated { [super setEditing:editing animated:animated]; // DRM: we want to perform the actions from this block in the main thread, but // asynchronously to avoid excessive delays which were causing issues. // dispatch_async(dispatch_get_main_queue(), ^void() { [self someAdditionalCode]; }); } 

Hacer mi endupdates después de resignfirstresponder resolvió mi problema (Tengo un UITextFIeld en mi celda personalizada)

 -(void)textfieldEditDone { .... [textField resignFirstResponder]; [self.tableView endUpdates]; 

Tuve el mismo problema con el post de error que aparece. Por lo que puedo ver, es causado por la recarga de la vista de la tabla desde una function llamada por el campo de text como parte de su protocolo de delegado. Ie textFieldDidEndEditing -> [controller.tableview reload …]

Para el logging, también encontré este post cuando se ejecutaba en iOS 6. Parece que algún código henetworkingado o importado tenía algo como esto:

 (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section { NSInteger rows = 0; if ([delegate respondsToSelector:@selector(numberOfItemsInSection:)]) { rows = [delegate numberOfItemsInSection:section]; [tableView beginUpdates]; [tableView endUpdates]; } } 

Cuando se eliminó la secuencia beginUpdate: / endUpdate: el problema desapareció por arte de magia.

Obviamente, esta es una vieja pregunta, pero espero que esto pueda ayudar a cualquier persona que todavía tenga este problema en iOS8 + porque esta sigue siendo la principal pregunta que surge para este post de error particular.

Estaba usando PINRemoteImage para async download una image a un UIImageView que estaba dentro de un UITableViewCell personalizado.

Con el fin de cambiar el tamaño de la fila correctamente (celdas dinámicas de altura utilizando el layout automático) una vez que la image se cargó, llamé:

 self.tableView beginUpdates; self.tableView endUpdates; 

Entonces obtuve el post "sin ruta de índice para la celda de tabla que se está reutilizando" y la aplicación se bloqueaba. Había pensado que el bloque PINRemoteImageManagerResult estaba en el hilo principal, pero resultó que no era así, por lo tanto, asegurando que las actualizaciones de inicio / final se llamaron en el hilo principal, se solucionó el problema.

 dispatch_async(dispatch_get_main_queue(), ^(void){ [self.tableView beginUpdates]; [self.tableView endUpdates]; }); 

Bueno, solo he usado la mayor parte del día tratando de resolver esto, así que espero que esta explicación alternativa salve a alguien más en algún momento.

Tuve una vista de tabla que estaba dando este post a veces , al cargar. Resultó ser causado por las notifications de KVO para los objects Core Data que disparaban mientras se cargaba la vista. (Al observar un cambio, mi controller intentó llamar a reloadData en la vista de tabla en cuestión. Se solucionó al no observar los objects hasta que la vista había terminado de cargarse (anteriormente comencé a observar el object una vez que se asignó a través del acceso)

TLDR: comtesting si puedes intentar volver a cargar tus datos desde algo más que el hilo principal.

Tal vez esto ayude a alguien: una vez tuve este error al actualizar una celda de vista de tabla única. Quise hacer algo como

 NSIndexPath *reloadRow = [NSIndexPath indexPathForRow:1 inSection:2]; [self._mainTableView reloadRowsAtIndexPaths:@[reloadWebViewRow] withRowAnimation:UITableViewRowAnimationFade]; 

Pero accidentalmente, escribí

 NSIndexPath *reloadRow = [NSIndexPath indexPathForItem:1 inSection:2]; 

Observe la diferencia de los dos paths indexpaths: uno se crea con indexPathForItem (incorrecto), el otro con indexPathForRow (correcto). Todo esto resultó en un comportamiento muy extraño de tableView y el post de error en el título.

Parece que mi problema se activó cuando intentaba actualizar la interfaz de usuario dentro de una parte del código que era una callback de una llamada web. Resolví forzando las actualizaciones de la interfaz de usuario para que sucedan en el hilo principal. Utilicé un código como este.

 void runOnMainQueueWithoutDeadlocking(void (^block)(void)){ if ([NSThread isMainThread]) { block(); } else { dispatch_sync(dispatch_get_main_queue(), block); } } 

Lo llamo de la siguiente manera dentro del bloque de éxito de mi llamada web de background.

 runOnMainQueueWithoutDeadlocking(^{ [self.tableView beginUpdates]; [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView endUpdates]; }); 

Sin embargo, otra condición …

Esto sucedió cuando, al no querer un encabezado, regresé sin nil .

Fijar:

 func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return "" }