overview - Quelle est la signification du message "aucun chemin d'index pour la cellule de tableau en cours de réutilisation" dans iOS 6/7?



ios technology overview (10)

Depuis que j'ai commencé à compiler mon application avec iOS 6 (et depuis iOS 7), j'ai commencé à voir ce message. Je sais que la façon dont UITableViews va gérer les cellules est différente dans iOS 6 mais je n'ai pas eu besoin de modifier mon code pour continuer à travailler. Mais je suis inquiet que ce message puisse indiquer un problème potentiel que je ne vois pas encore. Quelqu'un peut-il nous éclairer?

https://src-bin.com


Answer #1

Ajout à la réponse acceptée (mluisbrown), je devais ajouter un autoresizingMask à la cellule d'en-tête, puisque le mien contenait une étiquette multi-ligne, à savoir

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

Answer #2

C'est un bug interne d'UIKit - comme mentionné dans les propres forums de développement d'Apple. Il est censé être corrigé dans les nouvelles versions de xcode, bien que je n'ai pas pu trouver d'informations sur la version corrigeant cela.


Answer #3

Eh bien, j'ai juste utilisé la meilleure partie d'une journée à essayer de comprendre cela, alors j'espère que cette explication alternative sauve quelqu'un d'autre un peu de temps.

J'ai eu une tableview qui donnait ce message parfois , lors du chargement. Il s'est avéré être provoqué par des notifications KVO pour les objets Core Data qui se déclenchent pendant le chargement de la vue. (En observant une modification, mon contrôleur a essayé d'appeler reloadData sur la tableview en question.) Fixé en n'observant pas les objets jusqu'à ce que la vue ait fini de charger (auparavant, j'ai commencé à observer l'objet une fois assigné via l'accesseur)

TLDR: Vérifiez si vous essayez de recharger vos données depuis autre chose que le thread principal.


Answer #4

En plus de mon post précédent (dans lequel j'ai mentionné que c'était apparemment un bug avec UIKit), j'ai été capable de trouver une solution pour mon cas particulier (dans lequel le message était lié à d'étranges problèmes de visualisation sur la table).

Apparemment, ma cellule personnalisée est surchargée -(void)setEditing:animated: prenait trop de temps pour revenir.

Mon code précédent était:

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

J'ai été capable de le réparer en le changeant en:

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

Answer #5

Il semble que mon problème a été déclenché lorsque j'ai essayé de mettre à jour l'interface utilisateur dans une partie du code qui était un rappel d'un appel Web. J'ai résolu en forçant les mises à jour de l'interface utilisateur à se produire sur le thread principal. J'ai utilisé du code comme ça.

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

Je l'appelle comme suit à l'intérieur du bloc de succès de mon appel Web de fond.

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

Answer #6

J'ai commencé à voir apparaître cette erreur dans le journal à partir d'iOS 7 beta 5, y compris dans la version iOS 7 GM / Release, alors que je ne l'avais jamais trouvée dans iOS 6 ou iOS 7. Après beaucoup d'expérimentation j'ai trouvé la cause:

UITableViewCell objets UITableViewCell pour mes vues d'en-tête de section et les tableView:viewForHeaderInSection: dans tableView:viewForHeaderInSection: Cela semble être une pratique courante, surtout depuis iOS 5 quand il est devenu facile de concevoir une vue d'en-tête de section en tant que prototype de cellule de vue de table dans un StoryBoard avec Interface Builder.

Lorsque j'ai modifié mon application pour utiliser uniquement des sous-classes UIView régulières pour mes vues d'en-tête de section, les erreurs disparaissaient et, plus important encore, ma vue de table arrêtait de supprimer aléatoirement les en-têtes de section!

Il semblerait que (depuis iOS 7 beta 5) UITableView interne un mappage de tous les objets UITableViewCell dans sa hiérarchie de vue et leurs chemins d'index respectifs. Étant donné qu'un en-tête de section (ou un en-tête de pied de table) n'a pas de chemin d'index, si vous utilisez un objet UITableViewCell pour ces vues, la vue table sera confuse lorsqu'elle trouve un UITableViewCell pour lequel elle n'a pas de chemin d'index, ce qui entraîne l'erreur "aucun chemin d'index pour la cellule de tableau en cours de réutilisation" et, si vous êtes malchanceux, afficher des problèmes dans votre vue de table:

MISE À JOUR : si vous avez accès aux forums de développement Apple, voici le fil de discussion (que j'ai commencé): https://devforums.apple.com/message/882042#882042

Comme suggéré dans ce thread, si vous ne voulez pas beaucoup factoriser, vous pouvez créer un wrapper UIView autour de votre UITableViewCell et le renvoyer comme vue d'en-tête de section.

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

return view;

Notez cependant que cette approche UIView "wrapper" ne fonctionnera pas correctement avec AutoLayout et la rotation des périphériques, donc je suggère que vous UIView une sous-classe UIView pour les cellules d'en-tête et de pied, pas une sous-classe UITableViewCell comme expliqué dans la partie principale de la réponse.


Answer #7

J'ai eu le même problème et il m'a fallu quelques heures pour traquer le problème. Il s'avère que [textField becomeFirstResponder] lors de la configuration des cellules (ici le textField faisait partie d'une tableview cell personnalisée); [textField becomeFirstResponder] à tour de rôle la notification keyboardWillShow qui, à son tour, a provoqué le chargement prématuré de la table, ce qui a provoqué l'infâme message " aucun chemin d'index pour la cellule de table réutilisée ".


Answer #8

Je retournerais le contentView de UITableViewCell au lieu de créer un wrapper .. ayant la contrainte-jabble fixée dans le storybord à l'esprit

return cell.contentView;

Answer #9

Pour l'anecdote, j'ai aussi rencontré ce message sous iOS 6. Il semble que du code hérité ou importé avait quelque chose comme ça:

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

        [tableView beginUpdates];
        [tableView endUpdates];
    }
}

Lorsque la séquence beginUpdate: / endUpdate: a été supprimée, le problème a disparu comme par magie.


Answer #10

Encore une autre condition ...

C'est arrivé quand, ne voulant pas d'en-tête, je suis retourné à nil .

Réparer:

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




ios7