211 votes

Comment savoir quand UITableView a terminé le ReloadData ?

J'essaie de faire défiler le bas d'un UITableView après qu'il ait terminé de l'exécuter. [self.tableView reloadData]

A l'origine, j'avais

 [self.tableView reloadData]
 NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection: ([self.tableView numberOfSections]-1)];

[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

Mais ensuite, j'ai lu que le reloadData est asynchrone, donc le défilement ne se produit pas puisque le self.tableView , [self.tableView numberOfSections] y [self.tableView numberOfRowsinSection sont toutes égales à 0.

Merci !

Ce qui est bizarre c'est que j'utilise :

[self.tableView reloadData];
NSLog(@"Number of Sections %d", [self.tableView numberOfSections]);
NSLog(@"Number of Rows %d", [self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1);

Dans la console, il retourne Sections = 1, Row = -1 ;

Quand je fais exactement les mêmes NSLogs en cellForRowAtIndexPath J'obtiens Sections = 1 et Row = 8 ; (8 est juste)

6voto

XJones Points 14327

Il semble que les gens lisent toujours cette question et les réponses. C'est pourquoi je modifie ma réponse pour enlever le mot Synchrone ce qui n'a rien à voir avec le sujet.

When [tableView reloadData] retourne, les structures de données internes derrière le tableView ont été mises à jour. Par conséquent, lorsque la méthode se termine, vous pouvez sans risque faire défiler les données jusqu'au bas de la page. J'ai vérifié cela dans ma propre application. La réponse largement acceptée de @rob-mayoff, bien qu'également confuse dans sa terminologie, reconnaît la même chose dans sa dernière mise à jour.

Si votre tableView ne défile pas vers le bas, vous avez peut-être un problème dans un autre code que vous n'avez pas affiché. Peut-être modifiez-vous les données après la fin du défilement et ne rechargez-vous pas et/ou ne faites-vous pas défiler les données vers le bas ?

Ajoutez une journalisation comme suit pour vérifier que les données de la table sont correctes après reloadData . J'ai le code suivant dans un exemple d'application et il fonctionne parfaitement.

// change the data source

NSLog(@"Before reload / sections = %d, last row = %d",
      [self.tableView numberOfSections],
      [self.tableView numberOfRowsInSection:[self.tableView numberOfSections]-1]);

[self.tableView reloadData];

NSLog(@"After reload / sections = %d, last row = %d",
      [self.tableView numberOfSections],
      [self.tableView numberOfRowsInSection:[self.tableView numberOfSections]-1]);

[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[self.tableView numberOfRowsInSection:[self.tableView numberOfSections]-1]-1
                                                          inSection:[self.tableView numberOfSections] - 1]
                      atScrollPosition:UITableViewScrollPositionBottom
                              animated:YES];

5voto

malcolmhall Points 1909

J'utilise cette astuce, je suis presque sûr de l'avoir déjà postée dans un duplicata de cette question :

-(void)tableViewDidLoadRows:(UITableView *)tableView{
    // do something after loading, e.g. select a cell.
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // trick to detect when table view has finished loading.
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tableViewDidLoadRows:) object:tableView];
    [self performSelector:@selector(tableViewDidLoadRows:) withObject:tableView afterDelay:0];

    // specific to your controller
    return self.objects.count;
}

4voto

Asha Antony Points 431

En fait, celui-ci a résolu mon problème :

-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

NSSet *visibleSections = [NSSet setWithArray:[[tableView indexPathsForVisibleRows] valueForKey:@"section"]];
if (visibleSections) {
    // hide the activityIndicator/Loader
}}

1voto

Shashi3456643 Points 21

Essayez de cette façon, ça va marcher

[tblViewTerms performSelectorOnMainThread:@selector(dataLoadDoneWithLastTermIndex:) withObject:lastTermIndex waitUntilDone:YES];waitUntilDone:YES];

@interface UITableView (TableViewCompletion)

-(void)dataLoadDoneWithLastTermIndex:(NSNumber*)lastTermIndex;

@end

@implementation UITableView(TableViewCompletion)

-(void)dataLoadDoneWithLastTermIndex:(NSNumber*)lastTermIndex
{
    NSLog(@"dataLoadDone");

NSIndexPath* indexPath = [NSIndexPath indexPathForRow: [lastTermIndex integerValue] inSection: 0];

[self selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];

}
@end

Je vais exécuter quand la table est complètement chargée

L'autre solution consiste à sous-classer UITableView.

1voto

Sam Points 315

J'ai fini par utiliser une variante de la solution de Shawn :

Créez une classe UITableView personnalisée avec un délégué :

protocol CustomTableViewDelegate {
    func CustomTableViewDidLayoutSubviews()
}

class CustomTableView: UITableView {

    var customDelegate: CustomTableViewDelegate?

    override func layoutSubviews() {
        super.layoutSubviews()
        self.customDelegate?.CustomTableViewDidLayoutSubviews()
    }
}

Ensuite, dans mon code, j'utilise

class SomeClass: UIViewController, CustomTableViewDelegate {

    @IBOutlet weak var myTableView: CustomTableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.myTableView.customDelegate = self
    }

    func CustomTableViewDidLayoutSubviews() {
        print("didlayoutsubviews")
        // DO other cool things here!!
    }
}

Assurez-vous également de définir votre vue de table comme CustomTableView dans le constructeur d'interface :

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X