Est-il possible de tourner la page par programme dans UIPageViewController?


Réponses:


235

Oui c'est possible avec la méthode:

- (void)setViewControllers:(NSArray *)viewControllers 
                 direction:(UIPageViewControllerNavigationDirection)direction 
                  animated:(BOOL)animated 
                completion:(void (^)(BOOL finished))completion;`

C'est la même méthode utilisée pour configurer le premier contrôleur de vue sur la page. Similaire, vous pouvez l'utiliser pour accéder à d'autres pages.

Je viewControllersme demande pourquoi un tableau et pas un contrôleur de vue unique?

C'est parce qu'un contrôleur de vue de page peut avoir une «colonne vertébrale» (comme dans iBooks), affichant 2 pages de contenu à la fois. Si vous affichez 1 page de contenu à la fois, passez simplement dans un tableau à 1 élément.

Un exemple dans Swift:

pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil)

2
Maintenant que la NDA est en place, cela peut-il être étendu un peu plus? Peut-être un exemple de code.
SpaceTrucker

11
Je pense que j'ai enfin compris ceci: UIPageViewController ne se soucie pas vraiment de la page sur laquelle il se trouve actuellement. Lorsque vous appelez setViewControllers, cela peut donner l'impression que vous vous éloignez de manière animée du contrôleur de vue actuel, mais qu'il ne recherche pas vraiment une page.
Amy

3
exemple: [self setViewControllers: @ [vcToMoveTo] direction: UIPageViewControllerNavigationDirectionForward animé: OUI achèvement: nil]; // où vcToMoveTo est un UIViewController
finneycanhelp

1
Si vous voulez continuer à utiliser UIPageControl, alors vous voudrez peut-être: l'index de self.currentIndex = viewControllerToMoveTo, puis pour presentationIndexForPageViewController, renvoyez self.currentIndex
brendan

3
Vérifiez stackoverflow.com/questions/22554877/… si vous devez également mettre à jour l'affichage de l'indicateur de page
Protongun

37

Étant donné que j'en avais également besoin, j'entrerai plus en détail sur la façon de procéder.

Remarque: je suppose que vous avez utilisé le formulaire de modèle standard pour générer votre UIPageViewControllerstructure - qui a à la fois le modelViewControlleret dataViewControllercréé lorsque vous l'appelez. Si vous ne comprenez pas ce que j'ai écrit, revenez en arrière et créez un nouveau projet qui utilise leUIPageViewController comme base. Vous comprendrez alors.

Ainsi, avoir besoin de retourner à une page particulière implique de configurer les différents éléments de la méthode énumérés ci-dessus. Pour cet exercice, je suppose qu'il s'agit d'une vue de paysage avec deux vues affichées. De plus, j'ai implémenté cela en tant qu'IBAction afin que cela puisse être fait en appuyant sur un bouton ou non - il est tout aussi facile de faire appel au sélecteur et de transmettre les éléments nécessaires.

Donc, pour cet exemple, vous avez besoin des deux contrôleurs de vue qui seront affichés - et éventuellement, que vous progressiez dans le livre ou que vous reculiez.

Notez que j'ai simplement codé en dur où aller aux pages 4 et 5 et utiliser un feuillet avant. De là, vous pouvez voir que tout ce que vous avez à faire est de passer les variables qui vous aideront à obtenir ces éléments ...

-(IBAction) flipToPage:(id)sender {

    // Grab the viewControllers at position 4 & 5 - note, your model is responsible for providing these.  
    // Technically, you could have them pre-made and passed in as an array containing the two items...

    DataViewController *firstViewController = [self.modelController viewControllerAtIndex:4 storyboard:self.storyboard];
    DataViewController *secondViewController = [self.modelController viewControllerAtIndex:5 storyboard:self.storyboard];

    //  Set up the array that holds these guys...

    NSArray *viewControllers = nil;

    viewControllers = [NSArray arrayWithObjects:firstViewController, secondViewController, nil];

    //  Now, tell the pageViewContoller to accept these guys and do the forward turn of the page.
    //  Again, forward is subjective - you could go backward.  Animation is optional but it's 
    //  a nice effect for your audience.

      [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];

    //  Voila' - c'est fin!  

}

2
J'ai la même exigence pour passer à une page spécifique. Mais le code ci-dessus ne semble pas fonctionner pour moi. Qu'est-ce que je fais mal? J'ai 19 pages.
GaneshT

Pouvons-nous utiliser cet extrait de code également lors de la fourniture des contrôleurs de vue via un objet de source de données?
Jens Kohl

20
Quelle classe étrangement mal implémentée, Apple.
devios1

29

Voici un autre exemple de code pour une vue paginée unique. L'implémentation de viewControllerAtIndex est omise ici, elle doit renvoyer le contrôleur de vue correct pour l'index donné.

- (void)changePage:(UIPageViewControllerNavigationDirection)direction {
    NSUInteger pageIndex = ((FooViewController *) [_pageViewController.viewControllers objectAtIndex:0]).pageIndex;

    if (direction == UIPageViewControllerNavigationDirectionForward) {
        pageIndex++;
    }
    else {
        pageIndex--;
    }

    FooViewController *viewController = [self viewControllerAtIndex:pageIndex];

    if (viewController == nil) {
        return;
    }

    [_pageViewController setViewControllers:@[viewController]
                                  direction:direction
                                   animated:YES
                                 completion:nil];
}

Les pages peuvent être modifiées en appelant

[self changePage:UIPageViewControllerNavigationDirectionReverse];
[self changePage:UIPageViewControllerNavigationDirectionForward];

Mais le contrôle d'index de page n'est pas mis à jour. Comment je fais ça?
thatzprem

1
Cette réponse fonctionne pour moi - notez cependant que si vous comptez sur les méthodes déléguées "didFinishAnimating" de UIPageViewController, elles ne seront pas déclenchées. Au lieu de cela, déplacez votre code de didFinishAnimating vers une méthode distincte et appelez cette méthode à partir du bloc d'achèvement sur la méthode setViewControllers.
DiscDev

1
@thatzprem Si vous souhaitez continuer à utiliser UIPageControl, vous voudrez peut-être: l'index de self.currentIndex = viewControllerToMoveTo, puis pour presentationIndexForPageViewController, renvoyer self.currentIndex
brendan

@thatzprem a raison. Chaque fois qu'il va à la même page, par exemple si nous avons 3 pages, alors à chaque fois il ira à la 2ème page seulement.
Tushar Lathiya

19

Je pourrais totalement manquer quelque chose ici, mais cette solution semble beaucoup plus simple que beaucoup d'autres proposées.

extension UIPageViewController {
    func goToNextPage(animated: Bool = true, completion: ((Bool) -> Void)? = nil) {
        if let currentViewController = viewControllers?[0] {
            if let nextPage = dataSource?.pageViewController(self, viewControllerAfter: currentViewController) {
                setViewControllers([nextPage], direction: .forward, animated: animated, completion: completion)
            }
        }
    }
}

1
Fonctionne très bien! Il suffit également de changer l'indicateur de page d'une manière ou d'une autre.
TruMan1

Très utile! Veuillez également nous donner une fonction pour goToFirstPage.
Mamta

Chaque fois qu'il va à la même page, par exemple, si nous avons 3 pages, alors à chaque fois, il ira à la 2ème page seulement.
Tushar Lathiya

15

Ce code a bien fonctionné pour moi, merci.

C'est ce que j'ai fait avec. Certaines méthodes pour avancer ou reculer et une pour accéder directement à une page particulière. C'est pour un document de 6 pages en mode portrait. Cela fonctionnera bien si vous le collez dans l'implémentation du RootController du modèle pageViewController.

-(IBAction)pageGoto:(id)sender {

    //get page to go to
    NSUInteger pageToGoTo = 4;

    //get current index of current page
    DataViewController *theCurrentViewController = [self.pageViewController.viewControllers   objectAtIndex:0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];

    //get the page(s) to go to
    DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(pageToGoTo - 1) storyboard:self.storyboard];

    DataViewController *secondPageViewController = [self.modelController viewControllerAtIndex:(pageToGoTo) storyboard:self.storyboard];

    //put it(or them if in landscape view) in an array
    NSArray *theViewControllers = nil;    
    theViewControllers = [NSArray arrayWithObjects:targetPageViewController, secondPageViewController, nil];


    //check which direction to animate page turn then turn page accordingly
    if (retreivedIndex < (pageToGoTo - 1) && retreivedIndex != (pageToGoTo - 1)){
        [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
    }

    if (retreivedIndex > (pageToGoTo - 1) && retreivedIndex != (pageToGoTo - 1)){
        [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:NULL];
    }

}


-(IBAction)pageFoward:(id)sender {

    //get current index of current page
    DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];

    //check that current page isn't first page
    if (retreivedIndex < 5){

        //get the page to go to
        DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(retreivedIndex + 1) storyboard:self.storyboard];

        //put it(or them if in landscape view) in an array
        NSArray *theViewControllers = nil;    
        theViewControllers = [NSArray arrayWithObjects:targetPageViewController, nil];

        //add page view
        [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];

    }

}


-(IBAction)pageBack:(id)sender {


    //get current index of current page
    DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
    NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];

    //check that current page isn't first page
    if (retreivedIndex > 0){

    //get the page to go to
    DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(retreivedIndex - 1) storyboard:self.storyboard];

    //put it(or them if in landscape view) in an array
    NSArray *theViewControllers = nil;    
    theViewControllers = [NSArray arrayWithObjects:targetPageViewController, nil];

    //add page view
    [self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:NULL];

    }

}

je veux l'utiliser pour le mode paysage où deux pages existent. comment l'utiliser là-bas. pouvez-vous s'il vous plaît guider.
iPhone par programmation

9

Swift 4:

J'avais besoin d'aller au contrôleur suivant lorsque j'appuie sur le prochain contrôleur de vue pagecontroller et que je mets également à jour l'index de pageControl, donc c'était la solution la meilleure et la plus simple pour moi :

let pageController = self.parent as! PageViewController

pageController.setViewControllers([parentVC.orderedViewControllers[1]], direction: .forward, animated: true, completion: nil)

pageController.pageControl.currentPage = 1

5

Qu'en est-il de l'utilisation des méthodes de dataSource?

UIViewController *controller = [pageViewController.dataSource pageViewController:self.pageViewController viewControllerAfterViewController:pageViewController.viewControllers.firstObject];
[pageViewController setViewControllers:@[controller] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

Analogiquement pour en arrière.


3

Dans Swift :

import UIKit

extension HomeViewController {

    // MARK: - Carousel management.

    func startTimerForMovingCarousel(let numberOfSecondsBetweenFiringsOfTheTimer: NSTimeInterval) {
        if (self.timerForMovingCarousel == nil) {
            self.timerForMovingCarousel = NSTimer.scheduledTimerWithTimeInterval(numberOfSecondsBetweenFiringsOfTheTimer,
                                                                            target: self,
                                                                            selector: "moveCarousel",
                                                                            userInfo: nil,
                                                                            repeats: true)
        }
    }

    func moveCarousel() {
        println("I move the carousel.")

        let currentContentViewControllerDisplayed = self.pageViewController!.viewControllers[0] as! ContentViewController

        var index: Int = currentContentViewControllerDisplayed.index

        if index == self.arrayViewControllers.count - 1 {
            index = 0
        } else {
            ++index
        }

        let contentViewControllerToDisplay = self.arrayViewControllers[index] as! ContentViewController

        self.pageViewController.setViewControllers([contentViewControllerToDisplay],
                                                    direction: UIPageViewControllerNavigationDirection.Forward,
                                                    animated: true,
                                                    completion: nil)

        self.pageControl.currentPage = contentViewControllerToDisplay.index
    }

    func invalidateTimerForMovingCarousel() {
        if (self.timerForMovingCarousel != nil) {
            self.timerForMovingCarousel.invalidate()
            self.timerForMovingCarousel = nil
        }
    }

}

1
Pourriez-vous s'il vous plaît me donner un exemple complet à ce sujet. Parce que je fais quelque chose comme ça. Comment utiliser cette extension avec mon code. Si vous le souhaitez, je peux vous envoyer le code.
Sam

2

Cependant, l'utilisation de cet appel de méthode 'self.pageViewController setViewControllers' n'appelle pas 'viewDidDissapear' sur le viewController pour la page qui a été refusée, tandis que la rotation manuelle d'une page appelle viewDidDissapear sur la page refusée. Je crois que c'est la cause de mon crash

"Le nombre de contrôleurs de vue fournis (0) ne correspond pas au nombre requis (1) pour la transition demandée"


essayez d'utiliser: - pageViewController: didFinishAnimating: previousViewControllers: transitionCompleted:
Graham

2

J'avais également besoin d'un bouton pour naviguer à gauche sur un PageViewController, qui devrait faire exactement ce que vous attendez du mouvement de balayage.

Étant donné que j'avais déjà quelques règles en place dans " pageViewController: viewControllerBeforeViewController " pour gérer la navigation naturelle par balayage, je voulais que le bouton réutilise tout ce code et je ne pouvais tout simplement pas me permettre d'utiliser des index spécifiques pour atteindre des pages comme le précédent réponses ont fait. Donc, j'ai dû prendre une solution alternative.

Veuillez noter que le code suivant est pour un contrôleur d'affichage de page qui est une propriété dans mon ViewController personnalisé et dont la colonne vertébrale est définie sur mi.

Voici le code que j'ai écrit pour mon bouton Naviguer à gauche:

- (IBAction)btnNavigateLeft_Click:(id)sender {

    // Calling the PageViewController to obtain the current left page
    UIViewController *currentLeftPage = [_pageController.viewControllers objectAtIndex:0];

    // Creating future pages to be displayed
    NSArray *newDisplayedPages = nil;
    UIViewController *newRightPage = nil;
    UIViewController *newLeftPage = nil;

    // Calling the delegate to obtain previous pages
    // My "pageViewController:viewControllerBeforeViewController" method returns nil if there is no such page (first page of the book).
    newRightPage = [self pageViewController:_pageController viewControllerBeforeViewController:currentLeftPage];
    if (newRightPage) {
        newLeftPage = [self pageViewController:_pageController viewControllerBeforeViewController:newRightPage];
    }

    if (newLeftPage) {
        newDisplayedPages = [[NSArray alloc] initWithObjects:newLeftPage, newRightPage, nil];
    }

    // If there are two new pages to display, show them with animation.
    if (newDisplayedPages) {
        [_pageController setViewControllers:newDisplayedPages direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
    }
}

Vous pouvez faire quelque chose de très similaire pour créer un bon bouton de navigation à partir d'ici.


2

Dans le cas où le CONTRÔLE DE PAGE pour indiquer la page actuelle est O && Vous voulez que les pages naviguent par défilement et également en cliquant sur les boutons personnalisés dans Page ViewController, ci-dessous peut être utile.

//Set Delegate & Data Source for PageView controller [Say in View Did Load]
   self.pageViewController.dataSource = self;
   self.pageViewController.delegate = self;

// Delegates called viewControllerBeforeViewController when User Scroll to previous page 

 - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{

    [_nextBtn setTitle:@"Next" forState:UIControlStateNormal];

    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;

    if (index == NSNotFound){
        return nil;
    }else if (index > 0){
        index--;
    }else{
        return nil;
    }        
    return [self viewControllerAtIndex:index];        
}

// Délégué appelé viewControllerAfterViewController lorsque l'utilisateur passe à la page suivante

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{

    NSUInteger index = ((PageContentViewController*) viewController).pageIndex;

if (index == NSNotFound){
    return nil;
}else if (index < 3){
    index++;
}else{
    return nil;
}
return [self viewControllerAtIndex:index];}

//Delegate called while transition of pages. The need to apply logic in this delegate is to maintain the index of current page.

 - (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{ 

buttonIndex = (int)((PageContentViewController*) pendingViewControllers.firstObject).pageIndex;

}

-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{    
if (buttonIndex == 0){
    _backButton.hidden = true;
}else if (buttonIndex == [self.pageImages count] - 1){
    _backButton.hidden = false;
    [_nextBtn setTitle:@"Begin" forState:UIControlStateNormal];
}else{
    _backButton.hidden = false;
}

}

// Logique du bouton personnalisé (précédent et suivant)

-(void)backBtnClicked:(id)sender{
    if (buttonIndex > 0){
buttonIndex -= 1;
    }
    if (buttonIndex < 1) {
        _backButton.hidden = YES;
    }
    if (buttonIndex >=0) {
         [_nextBtn setTitle:@"Next" forState:UIControlStateNormal];
        PageContentViewController *startingViewController = [self viewControllerAtIndex:buttonIndex];
        NSArray *viewControllers = @[startingViewController];
        [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
    }

}

-(void)nextBtnClicked:(id)sender{
if (buttonIndex < 3){
buttonIndex += 1;
}
if(buttonIndex == _pageImages.count){
   //Navigate Outside Pageview controller        
}else{        
    if (buttonIndex ==3) {

        [_nextBtn setTitle:@"Begin" forState:UIControlStateNormal];
    }
    _backButton.hidden = NO;

    PageContentViewController *startingViewController = [self viewControllerAtIndex:buttonIndex];
    NSArray *viewControllers = @[startingViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}

}

//BUTTON INDEX & MAX COUNT
-(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController{
    return [self.pageImages count];}

-(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController{
    return  buttonIndex;}

Vous avez publié presque exactement la même réponse à quatre questions. Si vous pensez que l'un d'eux est un double de l'autre, vous devez les marquer comme tels (et ne pas publier la même réponse plusieurs fois).
Jaap

Alors, puis-je poster le lien de cette question sur une autre question similaire, mais la solution est la même.
Yogesh Lolusare

1
Je ne veux pas juger ou quoi que ce soit, mais le formatage de votre code me semble très rebutant.
Lukas Petr

1
D'accord @Lukas, je vais le formater maintenant. Merci
Yogesh Lolusare

2
- (void)moveToPage {

    NSUInteger pageIndex = ((ContentViewController *) [self.pageViewController.viewControllers objectAtIndex:0]).pageIndex;

    pageIndex++;

    ContentViewController *viewController = [self viewControllerAtIndex:pageIndex];

if (viewController == nil) {
        return;
    }
    [self.pageViewController setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

}

// appelle maintenant cette méthode

[self moveToPage];

J'espère que ca fonctionne :)


1

Pour une seule page, je viens de modifier la réponse de @Jack Humphries

-(void)viewDidLoad
{
  counter = 0;
}
-(IBAction)buttonClick:(id)sender
{
  counter++;
  DataViewController *secondVC = [self.modelController viewControllerAtIndex:counter storyboard:self.storyboard];
  NSArray *viewControllers = nil;          
  viewControllers = [NSArray arrayWithObjects:secondVC, nil];          
  [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
}

0

Comme l'a souligné @samwize, la façon de paginer consiste à utiliser

setViewControllers:array

Voici comment je l'ai fait: ma source de données et le délégué sont séparés. Vous pouvez appeler cette méthode et modifier uniquement la vue "suivante". Auparavant, vous devez appliquer les règles de pagination. Autrement dit, vous devez vérifier la direction et le contrôleur suivant. Si vous utilisez cette méthode avec votre source de données personnalisée, le tableau de contrôleurs que vous affichez ne changera pas (puisque vous utiliserez un tableau personnalisé sur une sous-classe NSObject).

En utilisant votre propre source de données, la méthode définit simplement une nouvelle vue (avec une direction spécifique). Puisque vous contrôlerez toujours les pages qui s'afficheront lorsque vous les balayez normalement.


0

Je travaille dessus depuis hier et je l'ai finalement fait fonctionner. Je ne pouvais pas utiliser totalement le modèle standard, car j'ai trois viewControllers différents en tant que childviews:

1 - rootViewController;
2 - model;
3 - viewControllers
3.1 - VC1;
3.2 - VC2;
3.3 - VC3.
Note: all of VCs has Storyboard ID.

J'avais besoin d'un bouton de déclenchement uniquement dans le premier VC, j'ai donc ajouté une propriété pour pageViewController et model:

#import <UIKit/UIKit.h>
#import "Model.h"

@interface VC1 : UIViewController

@property (nonatomic, strong) UIPageViewController *thePageViewController;
@property (nonatomic, strong) SeuTimePagesModel *theModel;

@end

J'ai réécrit la méthode init du modèle pour passer le storyboard et la pageViewController en tant que paramètres, afin que je puisse les définir sur mon VC1:

- (id)initWithStoryboard:(UIStoryboard *)storyboard
   andPageViewController:(UIPageViewController *)controller
{
    if (self = [super init])
    {
        VC1 *vc1 = [storyboard instantiateViewControllerWithIdentifier:@"VC1"];
        vc1.pageViewController = controller;
        vc1.model = self;

        VC2 *vc2 = [storyboard instantiateViewControllerWithIdentifier:@"VC2"];
        VC3 *vc3 = [storyboard instantiateViewControllerWithIdentifier:@"VC3"];
        self.pageData = [[NSArray alloc] initWithObjects:vc1, vc2, vc3, nil];
    }

    return self;
}

Enfin, j'ai ajouté une IBAction dans mon vc1 pour déclencher la méthode pageViewController setViewControllers: direction: animated: completion ::

- (IBAction)go:(id)sender
{
    VC2 *vc2 = [_model.pages objectAtIndex:1];
    NSArray *viewControllers = @[vc2];
    [_pageViewController setViewControllers:viewControllers
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:YES
                                 completion:nil];
}

Remarque Je n'ai pas besoin de trouver les index des VC, mon bouton m'amène à mon deuxième VC, mais ce n'est pas difficile d'obtenir tous les index et de garder une trace de vos enfants:

- (IBAction)selecionaSeuTime:(id)sender
{
    NSUInteger index = [_model.pages indexOfObject:self];
    index++;

    VC2 *vc2 = [_model.pages objectAtIndex:1];
    NSArray *viewControllers = @[vc2];
    [_pageViewController setViewControllers:viewControllers
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:YES
                                 completion:nil];
}

J'espère que ça t'aide!


0

Voici une solution utilisant les méthodes UIPageViewControllerDataSource :

Le code effectue le suivi du contrôleur de vue affiché actuel dans UIPageViewController .

...
@property (nonatomic, strong) UIViewController *currentViewController;
@property (nonatomic, strong) UIViewController *nextViewController;
...

Initialisez d'abord currentViewController avec le contrôleur de vue initial défini pour UIPageViewController .

- (void) viewDidLoad {
    [super viewDidLoad];
    ...
    self.currentViewController = self.viewControllers[0];
    ...
    [self.pageViewController setViewControllers: @[self.currentViewController] direction: dir animated: YES completion: nil];
}

Ensuite , garder une trace de currentViewController dans les UIPageViewControllerDelegate méthodes: pageViewController: willTransitionToViewControllers: et pageViewController: didFinishAnimating: previousViewControllers: transitionCompleted: .


- (nullable UIViewController *) pageViewController: (UIPageViewController *) pageViewController viewControllerBeforeViewController: (UIViewController *) viewController {
    NSInteger idx = [self.viewControllers indexOfObject: viewController];
    if (idx > 0) {
        return self.viewControllers[idx - 1];
    } else {
        return nil;
    }
}

- (nullable UIViewController *) pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController: (UIViewController *) viewController {
    NSInteger idx = [self.viewControllers indexOfObject: viewController];
    if (idx == NSNotFound) {
        return nil;
    } else {
        if (idx + 1 < self.viewControllers.count) {
            return self.viewControllers[idx + 1];
        } else {
            return nil;
        }
    }
}

- (void) pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers {
    self.nextViewController = [pendingViewControllers firstObject];
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed {
    if (completed) {
        self.currentViewController = self.nextViewController;
    }
}

Enfin, dans la méthode de votre choix (dans l'exemple ci - dessous de - (IBAction) OnNext: (id) expéditeur ), vous pouvez programmation passer au contrôleur suivant ou précédent en utilisant UIPageViewControllerDataSouce méthodes pageViewController: viewControllerBeforeViewController: , pageViewController: viewControllerAfterViewController: pour obtenir le contrôleur de vue suivant ou précédent et accédez-y en appelant [self.pageViewController setViewControllers: @ [vc] direction: UIPageViewControllerNavigationDirectionForward animé: OUI achèvement: nil];


- (void) onNext {
    UIViewController *vc = [self pageViewController: self.tutorialViewController viewControllerAfterViewController: self.currentViewController];
    if (vc != nil) {
        self.currentViewController = vc;
        [self.tutorialViewController setViewControllers: @[vc] direction: UIPageViewControllerNavigationDirectionForward animated: YES completion: nil];
    }
}

Une explication détaillée aurait été très utile.
Taslim Oseni

@TaslimOseni merci d'avoir souligné que l'exemple n'était pas assez clair. J'ai ajouté une description de son fonctionnement, s'il vous plaît laissez-moi savoir si cela nécessite plus d'explications.
pconor le

0

Comme les ViewControllers sont intégrés dans PageViewController, tout ce que vous avez à faire est de:

  • Récupérez le contrôleur de vue parent et cast en tant que classe appropriée.
  • Utilisez cette propriété de source de données parents pour obtenir le prochain ViewController.
  • Utilisez la méthode SetParentViewControllers pour définir et passer à la page suivante.

Exemple dans Xamarin, mais fonctionnellement similaire à Swift, etc. Le code suivant serait dans le délégué Button Click dans l'un des ViewControllers affiché sous forme de page:

var parent = ParentViewController as WelcomePageViewController;
var next = parent.DataSource.GetNextViewController(parent, this);

parent.SetViewControllers(new UIViewController[] { next }, UIPageViewControllerNavigationDirection.Forward, true, null);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.