Ist es möglich, in UIPageViewController programmgesteuert umzublättern?

161

Ist es möglich, programmgesteuert umzublättern UIPageViewController?

RAGOpoR
quelle
1
Kannst du bitte einen Beispielcode dafür posten? Danke dir.
iPhone programmatisch

Antworten:

235

Ja, mit der Methode ist es möglich:

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

Dies ist die gleiche Methode, die zum Einrichten des ersten Ansichtscontrollers auf der Seite verwendet wird. Ebenso können Sie damit andere Seiten aufrufen.

Frage mich, warum viewControllersein Array und kein Single View Controller ist?

Dies liegt daran, dass ein Seitenaufruf-Controller (wie in iBooks) einen "Rücken" haben kann, auf dem jeweils 2 Seiten Inhalt angezeigt werden. Wenn Sie jeweils 1 Seite Inhalt anzeigen, übergeben Sie einfach ein Array mit 1 Elementen.

Ein Beispiel in Swift:

pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil)
Samwize
quelle
2
Kann die NDA nun, da sie läuft, noch ein bisschen erweitert werden? Vielleicht ein Codebeispiel.
SpaceTrucker
11
Ich glaube, ich verstehe das endlich: UIPageViewController kümmert sich nicht wirklich darum, auf welcher Seite es sich gerade befindet. Wenn Sie setViewControllers aufrufen, kann dies den Anschein erwecken, dass Sie animiert vom aktuellen View Controller weg navigieren, aber nicht wirklich nach einer Seite suchen.
Amy
3
Beispiel: [self setViewControllers: @ [vcToMoveTo] Richtung: UIPageViewControllerNavigationDirectionForward animiert: YES Vervollständigung: Null]; // wo vcToMoveTo ein UIViewController ist
finneycanhelp
1
Wenn Sie UIPageControl weiterhin verwenden möchten, möchten Sie möglicherweise: self.currentIndex = viewControllerToMoveTo-Index, dann geben Sie für PresentationIndexForPageViewController self.currentIndex
brendan
3
Überprüfen Sie stackoverflow.com/questions/22554877/…, wenn Sie auch die Seitenanzeige aktualisieren müssen
Protongun
37

Da ich das auch brauchte, werde ich näher darauf eingehen, wie das geht.

Hinweis: Ich gehe davon aus, dass Sie das Standardvorlagenformular zum Generieren Ihrer UIPageViewControllerStruktur verwendet haben - das sowohl das modelViewControllerals auch dataViewControllerdas beim Aufrufen erstellte Formular enthält . Wenn Sie nicht verstehen, was ich geschrieben habe, gehen Sie zurück und erstellen Sie ein neues Projekt, das das UIPageViewControllerals Grundlage verwendet. Du wirst es dann verstehen.

Wenn Sie also zu einer bestimmten Seite blättern müssen, müssen Sie die verschiedenen Teile der oben aufgeführten Methode einrichten. Für diese Übung gehe ich davon aus, dass es sich um eine Landschaftsansicht handelt, in der zwei Ansichten angezeigt werden. Außerdem habe ich dies als IBAction implementiert, damit es per Knopfdruck ausgeführt werden kann oder was nicht - es ist genauso einfach, einen Auswahlaufruf durchzuführen und die benötigten Elemente weiterzugeben.

Für dieses Beispiel benötigen Sie also die beiden angezeigten Ansichts-Controller - und optional, ob Sie im Buch vorwärts oder rückwärts gehen.

Beachten Sie, dass ich lediglich fest codiert habe, wohin ich auf den Seiten 4 und 5 gehen und einen Vorwärtsbeleg verwenden soll. Von hier aus können Sie sehen, dass Sie nur die Variablen übergeben müssen, die Ihnen helfen, diese Elemente zu erhalten ...

-(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!  

}
Joe
quelle
2
Ich habe die gleiche Anforderung, um zu einer bestimmten Seite zu wechseln. Aber der obige Code scheint für mich nicht zu funktionieren. Was mache ich falsch? Ich habe 19 Seiten.
GaneshT
Können wir dieses Code-Snippet auch verwenden, wenn wir die View-Controller über ein Datenquellenobjekt bereitstellen?
Jens Kohl
20
Was für eine bizarr schlecht implementierte Klasse, Apple.
Devios1
29

Hier ist ein weiteres Codebeispiel für eine einzelne Seitenansicht. Die Implementierung für viewControllerAtIndex wird hier weggelassen. Sie sollte den richtigen View Controller für den angegebenen Index zurückgeben.

- (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];
}

Seiten können durch Aufruf geändert werden

[self changePage:UIPageViewControllerNavigationDirectionReverse];
[self changePage:UIPageViewControllerNavigationDirectionForward];
lekksi
quelle
Das Seitenindex-Steuerelement wird jedoch nicht aktualisiert. Wie mache ich das?
Thatzprem
1
Diese Antwort funktioniert für mich - beachten Sie jedoch, dass wenn Sie sich auf die Delegatmethoden "didFinishAnimating" von UIPageViewController verlassen, diese nicht ausgelöst werden. Verschieben Sie stattdessen Ihren Code von didFinishAnimating in eine separate Methode und rufen Sie diese Methode aus dem Abschlussblock der setViewControllers-Methode auf.
DiscDev
1
@thatzprem Wenn Sie UIPageControl weiterhin verwenden möchten, möchten Sie möglicherweise: self.currentIndex = viewControllerToMoveTos Index, dann für PresentationIndexForPageViewController self.currentIndex
brendan
@thatzprem ist richtig. Jedes Mal, wenn es auf dieselbe Seite geht. Wenn wir zum Beispiel 3 Seiten haben, dann geht es jedes Mal nur auf die 2. Seite.
Tushar Lathiya
18

Ich könnte hier etwas völlig vermissen, aber diese Lösung scheint viel einfacher zu sein als viele andere vorgeschlagen.

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)
            }
        }
    }
}
wfbarksdale
quelle
1
Funktioniert super! Müssen nur irgendwie auch die Seitenanzeige ändern.
TruMan1
Wirklich hilfreich! Bitte geben Sie uns auch eine Funktion für goToFirstPage.
Mamta
Jedes Mal, wenn es auf dieselbe Seite geht. Wenn wir zum Beispiel 3 Seiten haben, dann geht es jedes Mal nur auf die 2. Seite.
Tushar Lathiya
15

Dieser Code hat bei mir gut funktioniert, danke.

Das habe ich damit gemacht. Einige Methoden zum Vorwärts- oder Rückwärtsgehen und eine zum direkten Aufrufen einer bestimmten Seite. Es ist für ein 6-seitiges Dokument in der Porträtansicht. Es funktioniert einwandfrei, wenn Sie es in die Implementierung des RootControllers der pageViewController-Vorlage einfügen.

-(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];

    }

}
Graham
quelle
Ich möchte es für den Querformatmodus verwenden, wo zwei Seiten existieren. wie man es dort benutzt. kannst du bitte führen.
iPhone programmatisch
9

Swift 4:

Ich musste zum nächsten Controller wechseln, wenn ich als nächstes auf einen Seitencontroller-Ansichtscontroller tippe und auch den pageControl-Index aktualisiere. Dies war also die beste und einfachste Lösung für mich :

let pageController = self.parent as! PageViewController

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

pageController.pageControl.currentPage = 1
Sam Bing
quelle
5

Was ist mit Methoden aus dataSource?

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

Analog für rückwärts.

JakubKnejzlik
quelle
3

In 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
        }
    }

}
König-Zauberer
quelle
1
Könnten Sie mir bitte ein vollständiges Beispiel dafür geben? Weil ich so etwas mache. Wie verwende ich diese Erweiterung mit meinem Code? Wenn Sie möchten, kann ich Ihnen den Code senden.
Saty
2

Bei Verwendung dieses Methodenaufrufs 'self.pageViewController setViewControllers' wird jedoch nicht 'viewDidDissapear' auf dem viewController für die Seite aufgerufen, die abgelehnt wurde, während beim manuellen Umblättern einer Seite viewDidDissapear auf der abgelehnten Seite aufgerufen wird. Ich glaube, das ist die Ursache für meinen Absturz

"Die Anzahl der bereitgestellten View-Controller (0) stimmt nicht mit der Anzahl überein, die für den angeforderten Übergang erforderlich ist (1)."

noRema
quelle
Versuchen Sie es mit: - pageViewController: didFinishAnimating: previousViewControllers: TransitionCompleted:
Graham
2

Ich brauchte auch eine Schaltfläche, um auf einem PageViewController nach links zu navigieren, eine, die genau das tun sollte, was Sie von der Wischbewegung erwarten würden.

Da in " pageViewController: viewControllerBeforeViewController " bereits einige Regeln für den Umgang mit der natürlichen Swipe-Navigation vorhanden waren, wollte ich, dass die Schaltfläche den gesamten Code wiederverwendet, und konnte es mir einfach nicht leisten, bestimmte Indizes zu verwenden zu verwenden, um Seiten wie zuvor zu erreichen Antworten haben. Also musste ich eine alternative Lösung wählen.

Bitte beachten Sie, dass der folgende Code für einen Page View Controller gilt, der eine Eigenschaft in meinem benutzerdefinierten ViewController ist und dessen Rücken auf Mitte gesetzt ist.

Hier ist der Code, den ich für meine Schaltfläche Nach links navigieren geschrieben habe:

- (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];
    }
}

Sie können von hier aus etwas sehr Ähnliches tun, um eine rechte Navigationsschaltfläche zu erstellen.

tuliomir
quelle
2

Falls PAGE CONTROL zur Anzeige der aktuellen Seite O && ist. Sie möchten, dass Seiten per Bildlauf navigieren und auch auf benutzerdefinierte Schaltflächen in Page ViewController klicken. Dies kann hilfreich sein.

//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];        
}

// Delegierten namens viewControllerAfterViewController delegieren, wenn Benutzer zur nächsten Seite blättern

- (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;
}

}}

// Benutzerdefinierte Schaltfläche (Zurück & Weiter) Logik

-(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;}
Yogesh Lolusare
quelle
Sie haben die fast exakt gleiche Antwort auf vier Fragen gepostet. Wenn Sie der Meinung sind, dass einer von ihnen ein Duplikat des anderen ist, sollten Sie sie als solche markieren (und nicht mehrmals dieselbe Antwort posten).
Jaap
Kann ich den Link dieser Frage über eine andere ähnliche Frage stellen, aber die Lösung ist dieselbe?
Yogesh Lolusare
1
Ich will nicht urteilen oder so, aber Ihre Code-Formatierung sieht für mich sehr abstoßend aus.
Lukas Petr
1
Richtig @Lukas, ich werde es jetzt formatieren. Danke
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];

}

// rufe jetzt diese Methode auf

[self moveToPage];

Ich hoffe, es funktioniert :)

D. Garcia
quelle
1

Für eine einzelne Seite habe ich gerade die Antwort von @Jack Humphries bearbeitet

-(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];
}
Smit Shah
quelle
0

Wie @samwize hervorhob, erfolgt die Paginierung mithilfe von

setViewControllers:array

So habe ich es gemacht: Ich habe meine Datenquelle und den Delegaten getrennt. Sie können diese Methode aufrufen und nur die "nächste" Ansicht ändern. Zuvor müssen Sie die Paging-Regeln anwenden. Das heißt, Sie müssen die Richtung und den nächsten Controller überprüfen. Wenn Sie diese Methode mit Ihrer benutzerdefinierten Datenquelle verwenden, ändert sich das angezeigte Array von Controllern nicht (da Sie ein benutzerdefiniertes Array für eine NSObject-Unterklasse verwenden).

Mit Ihrer eigenen Datenquelle legt die Methode nur eine neue Ansicht fest (mit einer bestimmten Richtung). Da steuern Sie weiterhin die Seiten, die beim normalen Wischen angezeigt werden.

Wolffan
quelle
0

Ich arbeite seit gestern daran und ich habe es endlich geschafft. Ich konnte die Standardvorlage nicht vollständig verwenden, da ich drei verschiedene viewController als untergeordnete Ansichten habe:

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

Ich brauchte nur in der ersten VC eine Auslösetaste, also habe ich eine Eigenschaft für pageViewController und model hinzugefügt:

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

@interface VC1 : UIViewController

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

@end

Ich habe die Init-Methode des Modells neu geschrieben, um Storyboard und pageViewController als Parameter zu übergeben, damit ich diese auf meine VC1 setzen kann:

- (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;
}

Schließlich habe ich in meinem ein IBAction VC1 den pageViewController Verfahren zu triggern setViewControllers: Richtung: animierte: Fertigstellung: :

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

Hinweis: Ich muss keine VCs-Indizes finden. Meine Schaltfläche führt mich zu meiner zweiten VC. Es ist jedoch nicht schwierig, alle Indizes abzurufen und Ihre untergeordneten Ansichten zu verfolgen:

- (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];
}

Ich hoffe es hilft dir!

Thomás Calmon
quelle
0

Hier ist eine Lösung mit UIPageViewControllerDataSource- Methoden:

Der Code verfolgt den aktuell angezeigten View Controller im UIPageViewController .

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

Initialisieren Sie zuerst currentViewController mit dem für den UIPageViewController festgelegten anfänglichen Ansichtscontroller .

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

Verfolgen Sie dann den aktuellen ViewController in den UIPageViewControllerDelegate- Methoden: pageViewController: willTransitionToViewControllers: und 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;
    }
}

Schließlich wird in dem Verfahren Ihrer Wahl (im Beispiel unten ist es - (IBAction) OnNext: (id) sender ) können Sie programmatisch wechseln zum nächsten oder vorherigen Controller UIPageViewControllerDataSouce Methoden pageViewController: viewControllerBeforeViewController: , pageViewController: viewControllerAfterViewController: zu erhalten den nächsten oder vorherigen View-Controller und navigieren Sie zu ihm, indem Sie [self.pageViewController setViewControllers: @ [vc] aufrufen: Richtung: UIPageViewControllerNavigationDirectionForward animiert: YES-Abschluss: 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];
    }
}
pconor
quelle
Eine ausführliche Erklärung wäre sehr nützlich gewesen.
Taslim Oseni
@TaslimOseni danke für den Hinweis, dass das Beispiel nicht klar genug war. Ich habe eine Beschreibung der Funktionsweise hinzugefügt. Bitte lassen Sie mich wissen, wenn weitere Erläuterungen erforderlich sind.
Pconor
0

Da die ViewController in den PageViewController eingebettet sind, müssen Sie lediglich Folgendes tun:

  • Rufen Sie den übergeordneten Ansichts-Controller ab und setzen Sie ihn als relevante Klasse um.
  • Verwenden Sie diese übergeordnete Datenquelleneigenschaft, um den nächsten ViewController abzurufen.
  • Verwenden Sie die SetParentViewControllers-Methode, um die nächste Seite festzulegen und zur nächsten überzugehen.

Beispiel in Xamarin, aber funktional ähnlich wie Swift usw. Der folgende Code befindet sich in Button Click-Delegat in einem der ViewController, die als Seite angezeigt werden:

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

parent.SetViewControllers(new UIViewController[] { next }, UIPageViewControllerNavigationDirection.Forward, true, null);
Grant K.
quelle