129 votes

UIRefreshControl - beginRefreshing ne fonctionne pas lorsque UITableViewController se trouve dans UINavigationController

J'ai configuré un UIRefreshControl dans mon UITableViewController (qui se trouve à l'intérieur d'un UINavigationController) et il fonctionne comme prévu (c'est-à-dire que le pull down déclenche l'événement correct). Cependant, si j'invoque de manière programmatique l'élément beginRefreshing sur le contrôle de rafraîchissement comme :

[self.refreshControl beginRefreshing];

Rien ne se passe. Il devrait s'animer vers le bas et montrer le spinner. Le site endRefreshing fonctionne correctement lorsque je l'appelle après l'actualisation.

J'ai créé un projet prototype de base avec ce comportement et il fonctionne correctement lorsque mon UITableViewController est ajouté directement au contrôleur de vue racine du délégué de l'application, par exemple :

self.viewController = tableViewController;
self.window.rootViewController = self.viewController;

Mais si j'ajoute le tableViewController à un UINavigationController d'abord, puis ajoutez le contrôleur de navigation comme l'élément rootViewController le beginRefreshing ne fonctionne plus. Par exemple

UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableViewController];
self.viewController = navController;
self.window.rootViewController = self.viewController;

J'ai l'impression que cela a quelque chose à voir avec les hiérarchies de vues imbriquées dans le contrôleur de navigation qui ne sont pas compatibles avec le contrôle de rafraîchissement - des suggestions ?

Merci

202voto

Dmitry Shevchenko Points 11398

Il semble que si vous lancez l'actualisation de manière programmatique, vous devez faire défiler la vue du tableau vous-même, par exemple en modifiant le décalage du contenu.

[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];

Je suppose que la raison en est qu'il n'est pas souhaitable de faire défiler les pages jusqu'à la commande d'actualisation lorsque l'utilisateur se trouve au milieu ou en bas de la vue du tableau.

Version Swift 2.2 par @muhasturk

self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)

En bref, pour que ce système soit portable, ajoutez cette extension.

UIRefreshControl+ProgrammaticallyBeginRefresh.swift

extension UIRefreshControl {
    func programaticallyBeginRefreshing(in tableView: UITableView) {
        beginRefreshing()
        let offsetPoint = CGPoint.init(x: 0, y: -frame.size.height)
        tableView.setContentOffset(offsetPoint, animated: true)        
    }
}

80voto

Igotit Points 161

UITableViewController a automaticallyAdjustsScrollViewInsets après iOS 7. La vue tableau peut déjà avoir contentOffset, généralement (0, -64).

Ainsi, la bonne façon d'afficher le contrôle de rafraîchissement après le début du rafraîchissement par programmation est d'ajouter la hauteur du contrôle de rafraîchissement au contentOffset existant.

 [self.refreshControl beginRefreshing];
 [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];

35voto

Chris Wagner Points 9668

Voici une extension Swift utilisant les stratégies décrites ci-dessus.

extension UIRefreshControl {
    func beginRefreshingManually() {
        if let scrollView = superview as? UIScrollView {
            scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - frame.height), animated: true)
        }
        beginRefreshing()
    }
}

15voto

Kyle Robson Points 606

Aucune des autres réponses n'a fonctionné pour moi. Elles permettaient d'afficher et de faire tourner la roue, mais l'action d'actualisation elle-même ne se produisait jamais. Ceci fonctionne :

id target = self;
SEL selector = @selector(example);
// Assuming at some point prior to triggering the refresh, you call the following line:
[self.refreshControl addTarget:target action:selector forControlEvents:UIControlEventValueChanged];

// This line makes the spinner start spinning
[self.refreshControl beginRefreshing];
// This line makes the spinner visible by pushing the table view/collection view down
[self.tableView setContentOffset:CGPointMake(0, -1.0f * self.refreshControl.frame.size.height) animated:YES];
// This line is what actually triggers the refresh action/selector
[self.refreshControl sendActionsForControlEvents:UIControlEventValueChanged];

Notez que cet exemple utilise une vue de table, mais il aurait tout aussi bien pu s'agir d'une vue de collection.

13voto

ancajic Points 705

L'approche déjà mentionnée :

[self.refreshControl beginRefreshing];
 [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];

rendrait le spinner visible. Mais il ne s'animerait pas. La seule chose que j'ai changée est l'ordre de ces deux méthodes et tout a fonctionné :

[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated:YES];
[self.refreshControl beginRefreshing];

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