L'en-tête UiTableView ne disparaît pas

J'ai un UITableView configuré comme style simple afin que je puisse avoir les vues d'en-tête bloquées sur le dessus de la table jusqu'à ce qu'un autre en-tête l'enlève.

Le problème est: Si j'ai un en-tête bloqué en haut de l'écran, et que je défile par programmation vers une autre partie de la table (où cet en-tête ne devrait pas apparaître du tout), ce UIView ne sera pas rejeté. C'est-à-dire que si je défile à nouveau vers cette partie de la table, un fantôme de cet en-tête sera visible sur cette partie de la table.

Voir capture d'écran

J'ai implémenté la méthode - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(nonnull UIView *)view forSection:(NSInteger)section pour comprendre ce qui se passe. J'ai trouvé que si je défile manuellement jusqu'à ce qu'un en-tête soit retiré de l'écran, ce délégué est appelé. Mais si je défile par programmation, le délégué n'est pas appelé.

En passant, j'ai essayé de faire défiler par programmation en utilisant deux methods différentes, et le problème est le même.

 - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated; - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated; 

Une solution de contournement que je peux imaginer implémente - (void)scrollViewDidScroll:(UIScrollView *)scrollView; , en filtrant toutes les vues d'en-tête qui sont en dehors de l'écran visible, et en les supprimant de superview. Je peux probablement le faire fonctionner, mais j'aimerais savoir s'il existe une autre meilleure solution.

[EDIT] Si j'appelle - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated; avec animated = YES, le bug ne se produit pas. Je peux aller avec cette solution, mais j'aimerais dans certains cas faire défiler sans animation.

Pas tout à fait sûr Je comprends votre problème entièrement, mais il semble que vos vues d'en-tête (certains UIView ) n'est pas rendu correctement une fois que vous faites défiler par programmation loin de cette zone / section, puis revenez.

Je ne suis pas sûr de la façon dont vous remplissez le contenu de votre vue d'en-tête, mais j'ai plusieurs applications qui exécutent UITableView avec plusieurs en-têtes de section qui nécessitent une mise à jour pour le défilement / contenu sans problème, tant que vous dessinez vos en-têtes avec ce délégué :

 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { // Per section, simply return the appropriate header view ... NSSsortingng *someIdentifier = [NSSsortingng ssortingngWithFormat:@"sectionHeaderView:<some #, letter, or tag>", <SOMETHING UNIQUE ADD HERE>]; UITableViewHeaderFooterView *myHeaderView = [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:someIdentifier]; if (!myHeaderView) { // No header view found with that ID. Make a new one } ... return myHeaderViewForSection; } 

De cette façon, que vous déplaciez le doigt ou que vous ajustiez par programmation le décalage de contenu qui vous convient le mieux, votre vue de table saura quoi dessiner, quand dessiner et où la placer.

Utiliser leurs delegates est un peu un frein car c'est un peu fastidieux au début, mais en utilisant le viewForHeaderInSection s'est avéré la seule façon dont j'ai jamais obtenu les résultats que (vous) vouliez.

J'espère que cela aide – encoding heureux!

TL; DR

Ne faites PAS défiler explicitement la vue beginUpdates entre beginUpdates et endUpdates .

Explication

J'utilise NSFetchedResultsController pour remplir la table. Ce sont mes implémentations pour certaines des methods de NSFetchedResultsControllerDelegate.

 - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [_conversationTableView beginUpdates]; } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [_conversationTableView endUpdates]; } 

Le problème est que endUpdates faisait une string d'appels qui terminait l'appel de ma méthode [self scrollToBottom] (qui était en réalité un code très moche). Cette méthode, comme son nom l'indique, appelle - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated; pour faire défiler la vue de la table vers le bas de la table.

Le défilement explicite de la table pendant un beginUpdatesendUpdates était le coupable de tout mon problème.

Solution

Faire défiler la vue de la table seulement après avoir fini endUpdates.

 - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [_conversationTableView beginUpdates]; } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [_conversationTableView endUpdates]; [self scrollToBottom]; } 

Note latérale

Cela a également résolu un problème où la vue de la table clignotait parfois lors du défilement.