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

3voto

lyzkov Points 540

En plus de la solution @Dymitry Shevchenko.

J'ai trouvé un bon moyen de contourner ce problème. Vous pouvez créer une extension à UIRefreshControl qui écrase la méthode :

// Adds code forgotten by Apple, that changes content offset of parent scroll view (table view).
- (void)beginRefreshing
{
    [super beginRefreshing];

    if ([self.superview isKindOfClass:[UIScrollView class]]) {
        UIScrollView *view = (UIScrollView *)self.superview;
        [view setContentOffset:CGPointMake(0, view.contentOffset.y - self.frame.size.height) animated:YES];
    }
}

Vous pouvez utiliser une nouvelle classe en définissant une classe personnalisée dans le champ Inspecteur de l'identité pour le contrôle de rafraîchissement dans Interface Builder.

3voto

muhasturk Points 1043

Fort Swift 2.2+

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

3voto

jkyin Points 138

Si vous utilisez Rxswift pour swift 3.1, vous pouvez utiliser ce qui suit :

func manualRefresh() {
    if let refreshControl = self.tableView.refreshControl {
        self.tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.height), animated: true)
        self.tableView.refreshControl?.beginRefreshing()
        self.tableView.refreshControl?.sendActions(for: .valueChanged)
    }
}

Cela fonctionne pour swift 3.1, iOS 10.

2voto

testé sur Swift 5

l'utiliser dans viewDidLoad()

fileprivate func showRefreshLoader() {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
        self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y - (self.refreshControl.frame.size.height)), animated: true)
        self.refreshControl.beginRefreshing() 
    }
}

0voto

WINSergey Points 95

J'utilise la même technique pour montrer à l'utilisateur le signe visuel "les données sont mises à jour". Le résultat est que l'utilisateur sort l'application de l'arrière-plan et les flux/listes seront mis à jour avec l'interface utilisateur, comme si l'utilisateur tirait les tableaux pour se rafraîchir. Ma version contient 3 choses

1) Qui envoie "réveillez-vous"

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationHaveToResetAllPages object:nil];
}

2) Observateur dans UIViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(forceUpdateData) name:kNotificationHaveToWakeUp:nil];
}

3)Le protocole

#pragma mark - ForcedDataUpdateProtocol

- (void)forceUpdateData {
    self.tableView.contentOffset = CGPointZero;

    if (self.refreshControl) {
        [self.refreshControl beginRefreshing];
        [self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:YES];
        [self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:1];
    }
}

result

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