Je souhaite modifier le décalage de la table lorsque le chargement est terminé et que ce décalage dépend du nombre de cellules chargées sur la table.
Est-ce de toute façon sur le SDK de savoir quand un chargement uitableview est terminé? Je ne vois rien ni sur les délégués ni sur les protocoles de source de données.
Je ne peux pas utiliser le décompte des sources de données en raison du chargement des cellules visibles uniquement.
ios
iphone
uitableview
emenegro
la source
la source
Réponses:
Améliorer la réponse @RichX:
lastRow
peut être les deux[tableView numberOfRowsInSection: 0] - 1
ou((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row
. Le code sera donc:MISE À JOUR: Eh bien, le commentaire de @ htafoya est juste. Si vous voulez que ce code détecte la fin du chargement de toutes les données à partir de la source, ce ne sera pas le cas, mais ce n'est pas la question d'origine. Ce code permet de détecter le moment où toutes les cellules censées être visibles sont affichées.
willDisplayCell:
utilisé ici pour une interface utilisateur plus fluide (une seule cellule s'affiche généralement rapidement après unwillDisplay:
appel). Vous pouvez également l'essayer avectableView:didEndDisplayingCell:
.la source
viewForFooterInSection
méthode.Version Swift 3 & 4 & 5:
la source
J'utilise toujours cette solution très simple:
la source
[tableView numberOfRowsInSection: 0] - 1
. Vous devez remplacer0
par la valeur requise. Mais ce n'est pas le problème. Le problème est que UITableView charge uniquement visible. Cependant((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row
résout le problème.Voici une autre option qui semble fonctionner pour moi. Dans la méthode déléguée viewForFooter, vérifiez s'il s'agit de la dernière section et ajoutez votre code à cet endroit. Cette approche est venue à l'esprit après avoir réalisé que willDisplayCell ne tient pas compte des pieds de page si vous en avez.
Je trouve que cette approche fonctionne mieux si vous cherchez à trouver le chargement final pour l'ensemble
UITableView
, et pas simplement les cellules visibles. En fonction de vos besoins, vous voudrez peut-être uniquement les cellules visibles, auquel cas la réponse de folex est un bon itinéraire.la source
nil
detableView:viewForFooterInSection:
ma mise en page dans iOS 7 en utilisant la mise en page automatique.return CGRectMake(0,0,0,0);
self.tableView.sectionFooterHeight = 0
. Quoi qu'il en soit, il semble insérer une vue de pied de page d'une hauteur d'environ 10. Je parie que je pourrais résoudre ce problème en ajoutant une contrainte de hauteur 0 à la vue que je retourne. Quoi qu'il en soit, je suis bon parce que je voulais en fait savoir comment démarrer UITableView sur la dernière cellule, mais j'ai vu cela en premier.Solution Swift 2:
la source
Utilisation de l'API privée:
Utilisation de l'API publique:
Une meilleure conception possible est d'ajouter les cellules visibles à un ensemble, puis lorsque vous avez besoin de vérifier si la table est chargée, vous pouvez à la place faire une boucle for autour de cet ensemble, par exemple
la source
Pour la version de réponse choisie dans Swift 3:
J'avais besoin de la variable isLoadingTableView parce que je voulais m'assurer que le chargement de la table est terminé avant de faire une sélection de cellule par défaut. Si vous ne l'incluez pas, chaque fois que vous faites défiler le tableau, votre code sera de nouveau appelé.
la source
La meilleure approche que je connaisse est la réponse d'Eric à: Être notifié quand UITableView a fini de demander des données?
Mise à jour: pour que cela fonctionne, je dois passer ces appels
-tableView:cellForRowAtIndexPath:
la source
Pour savoir quand une vue de tableau termine le chargement de son contenu, nous devons d'abord avoir une compréhension de base de la façon dont les vues sont affichées à l'écran.
Dans le cycle de vie d'une application, il y a 4 moments clés:
Les temps 2 et 3 sont totalement séparés. Pourquoi ? Pour des raisons de performances, nous ne souhaitons pas effectuer tous les calculs du moment 3 à chaque fois qu'une modification est effectuée.
Donc, je pense que vous êtes confronté à un cas comme celui-ci:
Quel est le problème ici?
Comme toute vue, une vue de table recharge son contenu paresseusement. En fait, si vous appelez
reloadData
plusieurs fois, cela ne créera pas de problèmes de performances. La vue tableau ne recalcule que la taille de son contenu en fonction de son implémentation déléguée et attend le moment 3 pour charger ses cellules. Cette fois, on appelle une passe de mise en page.Ok, comment entrer dans le pass de mise en page?
Pendant la passe de mise en page, l'application calcule tous les cadres de la hiérarchie de vues. Pour vous impliquer, vous pouvez remplacer les méthodes dédiées
layoutSubviews
,updateLayoutConstraints
etc. dans aUIView
et les méthodes équivalentes dans une sous-classe de contrôleur de vue.C'est exactement ce que fait une vue de table. Il remplace
layoutSubviews
et en fonction de votre implémentation de délégué, ajoute ou supprime des cellules. Il appellecellForRow
juste avant d'ajouter et de disposer une nouvelle cellule,willDisplay
juste après. Si vous avez appeléreloadData
ou simplement ajouté la vue tableau à la hiérarchie, la vue tableaux ajoute autant de cellules que nécessaire pour remplir son cadre à ce moment clé.D'accord, mais maintenant, comment savoir quand une vue de tableaux a fini de recharger son contenu?
Nous pouvons maintenant reformuler cette question: comment savoir quand une vue de tableau a fini de disposer ses sous-vues?
• Le moyen le plus simple est d'entrer dans la disposition de la vue tableau:
Notez que cette méthode est appelée plusieurs fois dans le cycle de vie de la vue table. En raison du défilement et du comportement de sortie de la file d'attente de la vue tableau, les cellules sont modifiées, supprimées et ajoutées souvent. Mais cela fonctionne, juste après le
super.layoutSubviews()
chargement des cellules. Cette solution équivaut à attendre l'willDisplay
événement du dernier chemin d'index. Cet événement est appelé lors de l'exécutionlayoutSubviews
de la vue tableau pour chaque cellule ajoutée.• Un autre moyen consiste à être appelé lorsque l'application termine une passe de mise en page.
Comme décrit dans la documentation , vous pouvez utiliser une option du
UIView.animate(withDuration:completion)
:Cette solution fonctionne mais l'écran se rafraîchira une fois entre le moment où la mise en page est terminée et le moment où le bloc est appelé. Ceci est équivalent à la
DispatchMain.async
solution mais spécifié.• Sinon, je préférerais forcer la mise en page de la vue tableau
Il existe une méthode dédiée pour forcer toute vue à calculer immédiatement ses cadres de sous-vue
layoutIfNeeded
:Attention cependant, cela supprimera le chargement différé utilisé par le système. L'appel répété de ces méthodes peut créer des problèmes de performances. Assurez-vous qu'ils ne seront pas appelés avant que le cadre de la vue de table ne soit calculé, sinon la vue de table sera chargée à nouveau et vous ne serez pas averti.
Je pense qu'il n'y a pas de solution parfaite. Le sous-classement des classes peut conduire à des trubles. Une passe de mise en page commence par le haut et va vers le bas, il n'est donc pas facile d'être averti lorsque toute la mise en page est terminée. Et
layoutIfNeeded()
pourrait créer des problèmes de performances, etc. Mais connaissant ces options, vous devriez être en mesure de penser à une alternative qui répondra à vos besoins.la source
Voici comment procéder dans Swift 3:
la source
voici comment je le fais dans Swift 3
la source
Voici ce que je ferais.
Dans votre classe de base (peut être rootVC BaseVc etc.),
A. Écrivez un protocole pour envoyer le rappel "DidFinishReloading".
B. Ecrivez une méthode générique pour recharger la vue de table.
Dans l'implémentation de la méthode de classe de base, appelez reloadData suivi de delegateMethod avec delay.
Confirmez le protocole d'achèvement de rechargement dans tous les contrôleurs de vue où vous avez besoin du rappel.
Référence: https://discussions.apple.com/thread/2598339?start=0&tstart=0
la source
La réponse @folex est juste.
Mais cela échouera si la tableView a plus d'une section affichée à la fois.
la source
Dans Swift, vous pouvez faire quelque chose comme ça. La condition suivante sera vraie chaque fois que vous atteindrez la fin de la table
la source
Je sais que cela est répondu, j'ajoute simplement une recommandation.
Selon la documentation suivante
https://www.objc.io/issues/2-concurrency/thread-safe-class-design/
La résolution des problèmes de synchronisation avec dispatch_async est une mauvaise idée. Je suggère que nous devrions gérer cela en ajoutant FLAG ou quelque chose.
la source
Si vous avez plusieurs sections, voici comment obtenir la dernière ligne de la dernière section (Swift 3):
la source
Tout à fait accidentellement, je suis tombé sur cette solution:
Vous devez définir le footerView avant d'obtenir le contentSize, par exemple dans viewDidLoad. Btw. la configuration du footeView vous permet de supprimer les séparateurs "inutilisés"
la source
Recherchez-vous le nombre total d'éléments qui seront affichés dans le tableau ou le total des éléments actuellement visibles? De toute façon .. Je crois que la méthode «viewDidLoad» s'exécute après que toutes les méthodes de source de données sont appelées. Cependant, cela ne fonctionnera que sur le premier chargement des données (si vous utilisez un seul alloc ViewController).
la source
Je copie le code d'Andrew et je l'élargis pour tenir compte du cas où vous n'avez qu'une ligne dans le tableau. Cela fonctionne si loin pour moi!
REMARQUE: J'utilise juste une section du code d'Andrew, alors gardez cela à l'esprit.
la source
Dans iOS7.0x, la solution est un peu différente. Voici ce que j'ai trouvé.
la source
Objectif c
Rapide
la source
UICollectionView
que pour autant que je sache.