En basculant trop rapidement entre les onglets dans UIPageViewController, l'application se bloque en ligne
[UIPageViewController queuingScrollView:didEndManualScroll:toRevealView:direction:animated:didFinish:didComplete:]
avec des erreurs Échec d'assertion et fin de l'application en raison d'une exception non interceptée 'NSInternalInconsistencyException', raison: 'Aucun contrôleur de vue ne gère la vue visible.
Journal des erreurs comme ci-dessous
*** Assertion failure in -[UIPageViewController queuingScrollView:didEndManualScroll:toRevealView:direction:animated:didFinish:didComplete:], /SourceCache/UIKit/UIKit-3318.0.1/UIPageViewController.m:1875
2014-09-29 11:34:00.770 Wowcher[193:9460] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'No view controller managing visible view <UIView: 0x1783fa80; frame = (0 0; 320 416); autoresize = W+RM+H+BM; layer = <CALayer: 0x17898540>>'
*** First throw call stack:
(0x219fbf87 0x2f15ac77 0x219fbe5d 0x226cb2c9 0x253f9fff 0x2546f8d3 0x2546f6b7 0x2546c2b9 0x254700db 0x25470f97 0x2546d037 0x24ea925f 0x2500a589 0x24ff7eef 0x24ea677d 0x252b8c81 0x24e70105 0x24e6e07f 0x24ea4b6d 0x24ea443d 0x24e7acc5 0x250ee513 0x24e79707 0x219c2807 0x219c1c1b 0x219c0299 0x2190ddb1 0x2190dbc3 0x28c99051 0x24ed9a31 0xd950b 0xca6e0)
libc++abi.dylib: terminating with uncaught exception of type NSException
Merci d'avance
Donc ma solution était d'ajouter un BOOL
qui garde la trace de mon état d'animation. Donc, avant de définir le nouveau ViewController
, je le modifie aussi:
if (!_transitionInProgress) {
_transitionInProgress = YES;
[self.pageController setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:^(BOOL finished) {
_transitionInProgress = !finished;
}];
}
J'attendrai donc la fin de mon animation avant de définir un nouveau contrôleur de vue. Dans mon cas, j'ai quelques boutons sur lesquels l'utilisateur peut appuyer pour changer de page. Cela les empêche également d'aller trop vite à travers eux, donc les animations sont toujours fluides et agréables
Il s'agit d'un bogue dans l'implémentation interne de UIPageViewController en mode défilement. Cela se produit lorsqu'une animation de transition se produit alors que le contrôleur de vue de page anime déjà une transition. Ce que j'ai fini par faire était d'empêcher l'interface utilisateur d'autoriser plusieurs défilements rapides. J'ai deux boutons, gauche et droite, qui font défiler le contrôleur de vue de page jusqu'au contrôleur de page précédent ou suivant. Je désactive le fonctionnement des boutons pendant qu'une animation est en cours. Le délégué du contrôleur de vue de page vous indique tout ce que vous devez savoir quand désactiver la fonctionnalité de l'interface utilisateur et quand la réactiver, une fois toutes les animations arrêtées.
Je suis également confronté à ce problème, mais le problème est que je ne peux pas reproduire le problème de manière cohérente, mais je peux voir dans les journaux de plantage que le problème existe.
J'ai le pageviewcontroller qui permet à l'utilisateur de glisser et aussi la vue défile par programme. L'application se bloque parfois lorsque vous entrez dans l'écran, mais dans les prochaines tentatives, cela fonctionne bien, donc c'est un peu fou. Même si je mets un correctif, je ne peux pas être sûr qu'il fonctionne car je ne peux pas le reproduire. Il semble que le code ci-dessous devrait le corriger (tiré de Suppression d'un contrôleur de vue de UIPageViewController ) au moins, l'écran se comporte mieux avec ce code. J'apprécierais vraiment si je peux obtenir quelques méthodes pour injecter ce plantage moi-même, afin de pouvoir vérifier le correctif.
- (void) setViewControllers:(NSArray*)viewControllers direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated completion:(void (^)(BOOL))completion {
if (!animated) {
[super setViewControllers:viewControllers direction:direction animated:NO completion:completion];
return;
}
[super setViewControllers:viewControllers direction:direction animated:YES completion:^(BOOL finished){
if (finished) {
dispatch_async(dispatch_get_main_queue(), ^{
[super setViewControllers:viewControllers direction:direction animated:NO completion:completion];
});
} else {
if (completion != NULL) {
completion(finished);
}
}
}];
}
Il y a une très bonne discussion ici:
Suppression d'un contrôleur de vue de UIPageViewController
La réponse acceptée en discute:
"Ne sachant pas exactement pourquoi cela s'est produit, j'ai fait marche arrière et j'ai finalement commencé à utiliser la réponse de Jai comme solution, créant un UIPageViewController
entièrement nouveau, le poussant sur un UINavigationController
, puis sortant l'ancienne. Gross, mais ça marche - surtout. J'ai trouvé que je reçois toujours des échecs d'assertion occasionnels du UIPageViewController
, comme celui-ci:
- Échec d'assertion dans - [UIPageViewController queueingScrollView: didEndManualScroll: toRevealView: direction: animated: didFinish: didComplete:], /SourceCache/UIKit_Sim/UIKit-2380.17/UIPageViewController.m:1820 $ 1 = 154507824 Aucun contrôleur de vue visible>
Et l'application se bloque. Pourquoi? Eh bien, en cherchant, j'ai trouvé cette autre question que j'ai mentionnée en haut, et en particulier la réponse acceptée qui prône mon idée originale, d'appeler simplement setViewControllers: animated:YES
puis dès qu'il a terminé d'appeler setViewControllers: animated:NO
avec les mêmes contrôleurs de vue pour réinitialiser le UIPageViewController
, mais il avait l'élément manquant: rappeler ce code dans la file d'attente principale! Voici le code: "
J'ai également fait face à la même situation et mon application dispose à la fois de boutons de balayage et de boutons suivant et précédent pour naviguer d'avant en arrière. Pour résoudre le problème, affectez une variable Bool locale à true lors de l'initialisation (disons var privé canScroll : Bool = true ) puis vérifiez l'état dans la première ligne de votre méthode de navigation à l'aide de guard, puis définissez la valeur Bool sur false avant setViewcontroller méthode. à la fin de l'animation, définissez le même booléen sur true de sorte que lorsque vous effectuez une action de balayage pendant que le contrôleur de vue effectue la transition, l'instruction de garde vérifie canScroll pour être vrai sinon il revient. Voilà comment vous pouvez éviter le problème de plantage en pagination ci-dessous est mon code pour la prochaine action.
@IBAction func nextAction(_ sender: Any) {
guard canScroll == true else { return } //check condition
guard featureCount > 0 else { return }
guard let index = self.viewControllerAtIndex(indexRow) else { return }
let startingViewController: OnBoardModelViewController = index
canScroll = false
pageViewController?.setViewControllers([startingViewController],
direction: UIPageViewControllerNavigationDirection.forward,
animated: true,
completion: {_ in
self.canScroll = true
})
}
J'ai résolu le problème en définissant edgesForExtendedLayout = UIRectEdgeNone
sur ma sous-classe UIPageViewController
:
- (instancetype)initWithTransitionStyle:(UIPageViewControllerTransitionStyle)style navigationOrientation:(UIPageViewControllerNavigationOrientation)navigationOrientation options:(NSDictionary<NSString *,id> *)options
{
self = [super initWithTransitionStyle:style navigationOrientation:navigationOrientation options:options];
self.edgesForExtendedLayout = UIRectEdgeNone;
return self;
}