UIPageViewController, comment puis-je correctement accéder à une page spécifique sans perturber le fonctionnement de l'ordre spécifié par la source de données?
J'ai trouvé quelques questions sur la façon de faire un UIPageViewController
accéder à une page spécifique, mais j'ai remarqué un problème ajouté avec le saut qu'aucune des réponses semblent reconnaître.
Sans entrer dans les détails de mon application iOS (qui est semblable à un paginé calendrier), voici ce que je suis en train de vivre. Je déclare une UIPageViewController
, la vue-contrôleur, et de mettre en œuvre une source de données.
//end of the init method
pageViewController = [[UIPageViewController alloc]
initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:nil];
pageViewController.dataSource = self;
[self jumpToDay:0];
}
//...
- (void)jumpToDay:(NSInteger)day {
UIViewController *controller = [self dequeuePreviousDayViewControllerWithDaysBack:day];
[pageViewController setViewControllers:@[controller]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSInteger days = ((THDayViewController *)viewController).daysAgo;
return [self dequeuePreviousDayViewControllerWithDaysBack:days + 1];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSInteger days = ((THDayViewController *)viewController).daysAgo;
return [self dequeuePreviousDayViewControllerWithDaysBack:days - 1];
}
- (UIViewController *)dequeuePreviousDayViewControllerWithDaysBack:(NSInteger)days {
return [[THPreviousDayViewController alloc] initWithDaysAgo:days];
}
Modifier Note: j'ai ajouté simplifié le code pour la file d'attente de la méthode. Même avec cette mise en œuvre blasphématoire j'ai exactement le même problème avec la page de commande.
L'initialisation de tous les travaux comme prévu. L'augmentation de la pagination tout fonctionne très bien. Le problème c'est que si j'appel jumpToDay
de plus, l'ordre devient confuse.
Si l'utilisateur est sur la journée -5 et les sauts de la journée 1, un défilement vers la gauche pour révéler le jour de -5 à nouveau à la place des 0 jours. Cela semble avoir quelque chose à voir avec la façon dont UIPageViewController
conserve une référence à la proximité de pages, mais je ne trouve pas de référence à une méthode qui permettrait de forcer l'actualisation du cache.
Des idées?
- Je ne pense pas que le problème a à voir avec la façon dont un contrôleur de la page conserve une référence à la proximité de pages, je ne pense pas qu'il n'a même que. Il est de votre responsabilité, dans la mise en œuvre de votre source de données, pour garder une trace des pages. Donc, quelque chose qui est probablement mal avec daysAgo ou avec la dequeuePreviousDayViewControllerwithdaysback: la méthode.
- avez-vous résoudre ce problème ? Je vais avoir le même problème ?
- Normalement je me serais admettre que c'est de ma faute, mais de la "file d'attente" méthode littéralement juste instancie un contrôleur de même type avec une référence interne à l'égard de "jours". Il n'a même pas de faire de la fantaisie de l'attente et allocing qu'une UITableView prend soin de ses dequeueing méthode.
- N'ai pas trouvé de solution, mais étant donné que ce besoin d'être fait aujourd'hui, je suis envisage le déploiement de mon propre pageviewcontroller classe. Je vais vous laisser savoir si ça fonctionne.
- J'allais rejoindre rdelmar de l'opinion. J'ai mis en place un UIPageViewController avec environ les mêmes propriétés, et je n'ai jamais eu aucun problème. Qu'obtenez-vous que de jours dans viewControllerBeforeViewController ?
- Eh bien, alors il y a quelque chose de mal avec daysAgo puisque c'est la seule chose à déterminer quel contrôleur est instanciée. Comme pour rouler vos propres, si vous êtes en train de faire une seule page à la fois, puis il ne me semble que l'affichage de la page contrôleur n'a que ça pour vous. J'ai fait une, j'ai appelé un anneau de contrôleur qui vous permet d'aller de l'avant et en arrière d'une page, et également de passer à une autre page. Il n'était pas difficile à mettre en œuvre mais mon actuel de la mise en œuvre instancie toutes les contrôleurs à l'avant, ce qui n'est pas très efficace en terme de mémoire.
- daysAgo est littéralement juste un accesseur pour la NSInteger passé dans la méthode init. Je suis d'accord avec vous qu'un UIPageViewController est probablement pas ce que je cherche dans cette situation compte tenu de certains des autres limites que j'en vois (par exemple, la capacité d'observer le contenu de décalage de pages). Pour votre bague de contrôleur, êtes-vous juste de jeter toutes les pages en un UIScrollView? J'ai vu certaines applications faire quelque chose de similaire, mais n'était pas sûr de savoir comment ils l'ont accompli.
- Cette question/réponse résout le problème beaucoup plus facile. stackoverflow.com/questions/22554877/...
Vous devez vous connecter pour publier un commentaire.
Programmation iOS6, par Matt Neuburg documents exacte de ce problème, et j'ai effectivement trouvé que cette solution se sent un peu mieux que la actuellement accepté de répondre. Cette solution, qui fonctionne très bien, a un effet secondaire négatif de l'animation à l'image avant/après, et puis discordante remplacement de cette page avec la page souhaitée. J'ai ressenti que c'était une drôle d'expérience utilisateur, et Matt solution prend soin de cela.
Alors j'ai couru dans la même situation que vous l'endroit où je devais être capable de "sauter" d'une page, puis trouva la commande foiré quand j'ai fait un geste en arrière d'une page. Aussi loin que j'ai été en mesure de dire, l'affichage de la page de contrôleur est certainement la mise en cache à la vue des contrôleurs et quand vous "sauter" d'une page, vous devez spécifier la direction: en avant ou en arrière. Il suppose alors que le nouveau-vue-contrôleur est un "voisin" à la vue précédente contrôleur et donc automatiquement présente la vue précédente contrôleur lorsque vous geste en retour. J'ai trouvé que cela se produit uniquement lorsque vous utilisez la
UIPageViewControllerTransitionStyleScroll
et pasUIPageViewControllerTransitionStylePageCurl
. La page curl style apparemment ne fait pas de même de la mise en cache depuis si vous "sauter" d'une page puis le geste de retour, il offre lapageViewController:viewController(Before/After)ViewController:
message à la source de données permettant de vous fournir le bon voisin-vue-contrôleur.Solution:
Lors de l'exécution d'un "saut" de la page, vous pouvez sauter vers le voisin de la page à la page (
animated:NO
) vous êtes le saut, puis à la fin du bloc de saut, saut à la page désirée. Cela permettra de mettre à jour le cache de telle manière que lorsque vous les gestes de retour, le bon voisin page sera affichée. L'inconvénient est que vous devrez créer deux contrôleurs de vue; celui que vous êtes en sautant et celui qui doit être affiché après des gestes.Voici le code à une catégorie que j'ai écrit pour
UIPageViewController
:Ce que vous pouvez faire pour tester cela est de créer une nouvelle Page Basée sur l'Application "et d'ajouter" un "goto" bouton qui va "sauter" d'un certain mois et ensuite geste en retour. Assurez-vous de définir le style de transition pour les faire défiler.
- Je utiliser cette fonction (je suis toujours dans le paysage, les 2 page mode)
Voici ma solution Swift être utilisé pour les sous-classes de
UIPageViewController
:Supposons que vous stocker un tableau de viewControllers dans
viewControllerArray
et la page en cours d'index dansupdateCurrentPageIndex
.Swift version de djibouti33 réponse:
Il est important de noter que ce n'est plus le cas dans iOS 10 et vous n'avez plus à utiliser la accepté de répondre à la solution. Il suffit de continuer comme toujours.
Je peux confirmer que ce problème, et qu'il ne se produit que lors de l'utilisation de
UIPageViewControllerTransitionStyleScroll
et pasUIPageViewControllerTransitionStylePageCurl
.Solution de contournement: Faire une boucle et appel
UIPageViewController setViewControllers
pour chaque tourne de page, jusqu'à ce que vous atteindre la page désirée.Ce qui maintient l'intérieur de la source de données d'index en UIPageViewController dans la synchro.
C'est la seule solution
J'ai eu une approche différente, devrait être possible si vos pages sont conçus pour être mis à jour après l'init:
Lorsque une page de manuel est sélectionné-je mettre à jour un drapeau
et puis force la page suivante pour recharger avec les données correctes:
Si vous n'avez pas besoin d'animer la nouvelle page, car je n'en avais pas, le code suivant a travaillé pour moi, a appelé "Valeur a Changé" dans le storyboard. Au lieu de changer entre les contrôleurs de vue, j'ai modifier les données associées à la vue actuelle du contrôleur.
currentIndex est là afin que je puisse mettre à jour le contrôle pagecontrol de currentPage quand j'ai glisser entre les pages.
pageDataSource dataForPage: retourne un tableau d'objets de données qui sont affichées par le pages.
Ici est un up-to-date Swift 3+ version de la réponse par @djibouti33 avec nettoyés syntaxe.
J'ai été aux prises avec ce problème depuis longtemps moi-même. Pour moi j'ai eu un UIPageViewController (je l'ai appelé PageController) charger à partir d'un storyboard et sur ce j'ai ajouter un UIViewController 'ContentVC'.
Je laisse le ContentVC prend en charge les données à charger sur la zone de contenu et de laisser PageController prend soin de la coulissantes/goto/PageIndicator mises à jour. Le ContentVC a un ivar CurrentPageIndex et envoie cette valeur à PageController donc PageController sait quelle page c'est sur. Dans mon .m fichier qui a PageController j'ai ces deux méthodes.
Notez que j'ai utilisé est défini à 0 et donc, à chaque fois PageVC recharge, il va à la première page que je ne veux pas, [auto viewControllerAtIndex:0].
Cette deuxième méthode est PageViewController de source de données de la méthode. presentationIndexForPageViewController sera mis en surbrillance point à droite de la page (la page que vous voulez). Notez que si nous revenons 0 ici la page de l'indicateur met en évidence le premier point qui indique la première page et nous n'en veux pas.
UTILISATION: