Можно ли программно повернуть страницу в UIPageViewController?

Можно ли программно перевернуть страницу в UIPageViewController?


person RAGOpoR    schedule 26.08.2011    source источник
comment
Полностью объяснено здесь: stackoverflow.com/a/26024779/294884 Обратите внимание на простейшую версию схемы   -  person Fattie    schedule 18.04.2021


Ответы (17)


Да, это возможно с помощью метода:

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

Это тот же метод, который используется для настройки первого контроллера представления на странице. Похоже, вы можете использовать его для перехода на другие страницы.

Интересно, почему viewControllers - это массив, а не отдельный контроллер представления?

Это потому, что контроллер просмотра страницы может иметь «корешок» (как в iBooks), отображающий 2 страницы контента за раз. Если вы отображаете по одной странице контента за раз, просто передайте массив из 1 элемента.

Пример в Swift:

pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil)
person samwize    schedule 30.08.2011
comment
Теперь, когда NDA вступило в силу, можно ли его еще немного расширить? Может быть, образец кода. - person SpaceTrucker; 01.11.2011
comment
Думаю, я наконец понял это: UIPageViewController на самом деле не заботится о том, на какой странице он сейчас находится. Когда вы вызываете setViewControllers, может показаться, что вы анимированно уходите от текущего контроллера представления, но на самом деле он не ищет страницу. - person Amy; 25.02.2014
comment
пример: [self setViewControllers: @ [vcToMoveTo] направление: UIPageViewControllerNavigationDirectionForward анимировано: ДА завершение: ноль]; // где vcToMoveTo - это UIViewController - person finneycanhelp; 09.11.2014
comment
Если вы хотите продолжить использование UIPageControl, вам может потребоваться: self.currentIndex = viewControllerToMoveTo index, затем для presentationIndexForPageViewController вернуть self.currentIndex - person brendan; 22.12.2015
comment
Убедитесь, что stackoverflow.com / questions / 22554877 / если еще нужно обновить отображение индикатора страницы - person Protongun; 13.07.2016
comment
Обратите внимание, что этот ответ не сработает для вас, если вы хотите быстро переключать контроллеры (например, с помощью следующей кнопки). В этом случае вы получите NSInternalInconsistencyException Unexpected view controller - person RareScrap; 23.09.2020

Поскольку мне это тоже было нужно, я более подробно расскажу, как это сделать.

Примечание: я предполагаю, что вы использовали стандартную форму шаблона для создания своей структуры UIPageViewController, в которой созданы как modelViewController, так и dataViewController, когда вы ее вызываете. Если вы не понимаете, что я написал - вернитесь и создайте новый проект, который использует UIPageViewController в качестве основы. Тогда ты поймешь.

Таким образом, для перехода на определенную страницу необходимо настроить различные элементы метода, перечисленного выше. В этом упражнении я предполагаю, что это альбомный вид с двумя отображаемыми видами. Кроме того, я реализовал это как IBAction, чтобы его можно было сделать одним нажатием кнопки или чем-то еще - это точно так же, как легко сделать это вызовом селектора и передать необходимые элементы.

Итак, для этого примера вам понадобятся два контроллера представления, которые будут отображаться - и, при необходимости, независимо от того, идете ли вы вперед по книге или назад.

Обратите внимание, что я просто жестко запрограммировал, где перейти к страницам 4 и 5 и использовать прямую опечатку. Отсюда вы можете видеть, что все, что вам нужно сделать, это передать переменные, которые помогут вам получить эти предметы ...

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

}
person Joe    schedule 04.11.2011
comment
У меня такое же требование для перехода на определенную страницу. Но мне кажется, что приведенный выше код не работает. Что я делаю неправильно? У меня 19 страниц. - person GaneshT; 26.12.2011
comment
Можем ли мы использовать этот фрагмент кода также при предоставлении контроллеров представления через объект источника данных? - person Jens Kohl; 10.08.2012
comment
Что за причудливо плохо реализованный класс, Apple. - person devios1; 01.07.2014

Вот еще один пример кода для одностраничного представления. Реализация для viewControllerAtIndex здесь опущена, она должна возвращать правильный контроллер представления для данного индекса.

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

Страницы можно сменить, позвонив

[self changePage:UIPageViewControllerNavigationDirectionReverse];
[self changePage:UIPageViewControllerNavigationDirectionForward];
person lekksi    schedule 11.04.2014
comment
Но элемент управления индексом страницы не обновляется. Как я могу это сделать? - person thatzprem; 17.11.2014
comment
Этот ответ работает для меня - однако обратите внимание, что если вы полагаетесь на методы делегата didFinishAnimating UIPageViewController, они не будут запущены. Вместо этого переместите свой код из didFinishAnimating в отдельный метод и вызовите этот метод из блока завершения в методе setViewControllers. - person DiscDev; 05.04.2015
comment
@thatzprem Если вы хотите продолжить использование UIPageControl, вам может потребоваться: self.currentIndex = viewControllerToMoveTo index, затем для presentationIndexForPageViewController вернуть self.currentIndex - person brendan; 22.12.2015
comment
@thatzprem прав. Каждый раз он переходит на одну и ту же страницу. Например, если у нас есть 3 страницы, то каждый раз он будет переходить только на 2-ю страницу. - person Tushar Lathiya; 09.08.2018

Я мог полностью упустить что-то здесь, но это решение кажется намного проще, чем многие другие предложенные.

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)
            }
        }
    }
}
person wfbarksdale    schedule 30.03.2017
comment
Работает отлично! Просто надо еще как-нибудь поменять индикатор страницы. - person TruMan1; 06.06.2017
comment
Действительно полезно! Пожалуйста, дайте нам функцию для goToFirstPage. - person Mamta; 19.06.2017
comment
Каждый раз он переходит на одну и ту же страницу. Например, если у нас есть 3 страницы, то каждый раз он будет переходить только на 2-ю страницу. - person Tushar Lathiya; 09.08.2018
comment
Отличное решение. - person Behzad Moulodi; 07.03.2021

Этот код у меня отлично сработал, спасибо.

Вот что я с ним сделал. Некоторые методы для перехода вперед или назад и один для перехода непосредственно к определенной странице. Это для 6-страничного документа в портретной ориентации. Он будет работать нормально, если вы вставите его в реализацию RootController шаблона 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];

    }

}
person Graham    schedule 30.12.2011
comment
Я хочу использовать его для ландшафтного режима, когда существуют две страницы. как его там использовать. не могли бы вы направить. - person iPhone Programmatically; 14.12.2012

Swift 4:

Мне нужно было перейти к следующему контроллеру, когда я нажимаю далее на контроллере представления pagecontroller, а также обновляю индекс pageControl, так что это было лучшее и наиболее простое решение для меня:

let pageController = self.parent as! PageViewController

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

pageController.pageControl.currentPage = 1
person Sam Bing    schedule 08.02.2018

А как насчет использования методов из источника данных?

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

Аналогично обратному.

person JakubKnejzlik    schedule 09.10.2015

Однако использование этого вызова метода self.pageViewController setViewControllers не вызывает viewDidDissapear в viewController для страницы, которая была отклонена, тогда как ручное переключение страницы вызывает viewDidDissapear на отклоненной странице. Я считаю, что это причина моего крушения

«Количество предоставленных контроллеров представления (0) не соответствует количеству, необходимому (1) для запрошенного перехода»

person noRema    schedule 21.09.2012
comment
попробуйте использовать: - pageViewController: didFinishAnimating: previousViewControllers: transitionCompleted: - person Graham; 02.01.2013

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

}
person King-Wizard    schedule 06.06.2015
comment
Не могли бы вы привести мне полный пример этого. Потому что я делаю что-то подобное. Как использовать это расширение с моим кодом. Если хотите, я могу отправить вам код. - person Saty; 28.09.2015

Мне также нужна была кнопка для перехода влево на PageViewController, которая должна делать именно то, что вы ожидаете от движения смахивания.

Поскольку у меня уже было несколько правил внутри "pageViewController: viewControllerBeforeViewController" для работы с естественной навигацией смахиванием, я хотел, чтобы кнопка повторно использовала весь этот код, и просто не мог себе позволить использовать определенные индексы для доступа к страницам, как это делали предыдущие ответы. Итак, мне пришлось принять альтернативное решение.

Обратите внимание, что следующий код предназначен для контроллера просмотра страницы, который является свойством внутри моего настраиваемого ViewController, и для его позвоночника установлено значение mid.

Вот код, который я написал для кнопки «Переход влево»:

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

Вы можете сделать что-то очень похожее, чтобы создать правую кнопку навигации отсюда.

person tuliomir    schedule 10.02.2013

В случае если PAGE CONTROL для обозначения текущей страницы O && Вы хотите, чтобы страницы перемещались с помощью прокрутки, а также путем нажатия настраиваемых кнопок в Page ViewController, приведенное ниже может быть полезно.

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

// Делегат вызывает viewControllerAfterViewController, когда пользователь переходит на следующую страницу

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

}

// Логика пользовательской кнопки (предыдущая и следующая)

-(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;}
person Yogesh Lolusare    schedule 28.08.2016
comment
Вы отправили почти тот же ответ на четыре вопроса. Если вы считаете, что один из них является копией другого, вы должны отметить их как таковые (и не публиковать один и тот же ответ несколько раз). - person Jaap; 28.08.2016
comment
Итак, могу ли я опубликовать ссылку на этот вопрос по другому аналогичному вопросу, но решение такое же. - person Yogesh Lolusare; 29.08.2016
comment
Я не собираюсь судить или что-то в этом роде, но ваше форматирование кода мне кажется очень неприятным. - person Lukas Petr; 08.03.2017
comment
Правильно, @Lukas, сейчас буду форматировать. Спасибо - person Yogesh Lolusare; 08.03.2017

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

}

// теперь вызовем этот метод

[self moveToPage];

Надеюсь это работает :)

person D.Garcia    schedule 19.09.2017

Для одной страницы я только что отредактировал ответ @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];
}
person Smit Shah    schedule 27.06.2015

Как отметил @samwize, способ разбивки на страницы заключается в использовании

setViewControllers:array

Вот как я это сделал: у меня есть источник данных и делегат отдельно. Вы можете вызвать этот метод и изменить только «следующее» представление. Раньше вам нужно было применить правила разбиения на страницы. То есть вам нужно проверить направление и следующий контроллер. Если вы используете этот метод со своим настраиваемым источником данных, массив отображаемых контроллеров не изменится (поскольку вы будете использовать настраиваемый массив в подклассе NSObject).

Используя ваш собственный источник данных, метод просто устанавливает новое представление (с определенным направлением). Поскольку вы по-прежнему будете контролировать страницы, которые будут отображаться при обычном пролистывании.

person wolffan    schedule 20.03.2014

Я работаю над этим со вчерашнего дня, и я наконец-то заработал. Я не мог полностью использовать стандартный шаблон, потому что у меня есть три разных viewController как childviews:

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

Мне нужна была кнопка триггера только в первом VC, поэтому я добавил одно свойство для pageViewController и модели:

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

@interface VC1 : UIViewController

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

@end

Я переписал метод инициализации модели, чтобы передать раскадровку и pageViewController в качестве параметров, чтобы я мог установить их в свой 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;
}

Наконец, я добавил IBAction в свой vc1 для запуска метода pageViewController setViewControllers: direction: animated: завершения::

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

Примечание. Мне не нужно искать индексы венчурных капиталистов, моя кнопка переводит меня ко второму венчурному капиталу, но получить все индексы и отслеживать ваши дочерние просмотры несложно:

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

Надеюсь, это вам поможет!

person Thomás Pereira    schedule 10.06.2014

Вот решение, использующее методы UIPageViewControllerDataSource:

Код отслеживает текущий отображаемый контроллер представления в UIPageViewController.

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

Сначала инициализируйте currentViewController начальным контроллером представления, установленным для UIPageViewController.

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


Затем отслеживайте currentViewController в методах UIPageViewControllerDelegate: pageViewController: willTransitionToViewControllers: и 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;
    }
}

Наконец, в методе по вашему выбору (в примере ниже это - (IBAction) onNext: (id) sender) вы можете программно переключиться на следующий или предыдущий контроллер с помощью UIPageViewControllerDataSouce методы pageViewController: viewControllerBeforeViewController:, pageViewController: viewControllerAfterViewController:, чтобы получить следующий или предыдущий контроллер представления и перейти к нему, вызвав [self.pageViewController setViewControllers: @ [vc] direction: UIPageViewControllerNavigationDirectionForward анимировано: ДА, завершение: ноль];


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

person pconor    schedule 11.04.2019
comment
Подробное объяснение было бы очень полезным. - person Taslim Oseni; 11.04.2019
comment
@TaslimOseni благодарит за указание на то, что пример недостаточно ясен. Я добавил описание того, как это работает, дайте мне знать, если это требует дополнительных объяснений. - person pconor; 11.04.2019

Поскольку ViewControllers встроены в PageViewController, все, что вам нужно сделать, это:

  • Получите родительский контроллер представления и приведите его к соответствующему классу.
  • Используйте это свойство родительского источника данных, чтобы получить следующий ViewController.
  • Используйте метод SetParentViewControllers для установки и перехода на следующую страницу.

Пример в Xamarin, но функционально похож на Swift и т. Д. Следующий код будет в делегате нажатия кнопки в одном из ViewControllers, отображаемых в виде страницы:

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

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