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

161

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

RAGOpoR
источник
1
Можете ли вы опубликовать любой пример кода для него. Благодарю вас.
iPhone программно

Ответы:

235

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

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

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

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

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

Пример в Swift:

pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil)
samwize
источник
2
Теперь, когда NDA работает, это может быть расширено? Может быть, пример кода.
SpaceTrucker
11
Я думаю, что наконец-то понял это: UIPageViewController на самом деле не заботится о том, на какой странице он сейчас находится. Когда вы вызываете setViewControllers, может показаться, что вы анимируете навигацию от текущего контроллера представления, но на самом деле он не ищет страницу.
Эми
3
пример: [self setViewControllers: @ [vcToMoveTo] направление: UIPageViewControllerNavigationDirectionForward animated: YES завершение: nil]; // где vcToMoveTo - UIViewController
finneycanhelp
1
Если вы хотите продолжать использовать UIPageControl, то вы можете захотеть: индекс self.currentIndex = viewControllerToMoveTo, а затем для presentationIndexForPageViewController вернуть self.currentIndex
brendan
3
Проверьте stackoverflow.com/questions/22554877/… если вам также нужно обновить отображение индикатора страницы
Protongun
37

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

Примечание: я предполагаю, что вы использовали стандартную шаблонную форму для генерации вашей 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!  

}
Джо
источник
2
У меня такое же требование, чтобы перейти на определенную страницу. Но приведенный выше код не работает для меня. Что я делаю не так? У меня 19 страниц.
ГанешТ
Можем ли мы использовать этот фрагмент кода также при предоставлении контроллеров представления через объект источника данных?
Дженс Кол
20
Какой странно плохо реализованный класс, Apple.
devios1
29

Вот еще один пример кода для одного постраничного представления. Реализация для 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];
lekksi
источник
Но элемент управления индексом страницы не обновляется. Как я могу это сделать?
thatzprem
1
Этот ответ работает для меня - обратите внимание, однако, что если вы полагаетесь на методы делегата didFinishAnimating UIPageViewController, они не будут запущены. Вместо этого переместите код из didFinishAnimating в отдельный метод и вызовите этот метод из блока завершения в методе setViewControllers.
DiscDev
1
@thatzprem Если вы хотите продолжить использовать UIPageControl, то вы можете захотеть: индекс self.currentIndex = viewControllerToMoveTo, а затем для presentationIndexForPageViewController вернуть self.currentIndex
brendan
@thatzprem прав. Каждый раз, когда он идет на одну и ту же страницу. Например, если у нас есть 3 страницы, то каждый раз он будет идти только на 2-ю страницу.
Тушар Латия
19

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

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
источник
1
Прекрасно работает! Просто нужно как-то изменить индикатор страницы.
TruMan1
Действительно полезно! Пожалуйста, дайте нам функцию для goToFirstPage тоже.
Мамта
Каждый раз, когда он идет на одну и ту же страницу. Например, если у нас есть 3 страницы, то каждый раз он будет идти только на 2-ю страницу.
Тушар Латия
15

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

Это то, что я сделал с этим. Некоторые методы для перехода вперед или назад и один для перехода непосредственно на определенную страницу. Это для 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];

    }

}
Грэхем
источник
Я хочу использовать его для ландшафтного режима, где существуют две страницы. как это использовать там. Можете ли вы, пожалуйста, руководство.
iPhone программно
9

Свифт 4:

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

let pageController = self.parent as! PageViewController

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

pageController.pageControl.currentPage = 1
Сэм Бинг
источник
5

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

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

Аналогично для обратной.

JakubKnejzlik
источник
3

В Свифте :

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
Не могли бы вы дать мне полный пример для этого. Потому что я делаю что-то подобное. Как использовать это расширение с моим кодом. Если вы хотите, я могу отправить вам код.
Saty
2

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

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

noRema
источник
попробуйте использовать: - pageViewController: didFinishAnimating: previousViewControllers: transitionCompleted:
Грэм
2

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

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

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

Вот код, который я написал для моей левой кнопки навигации:

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

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

tuliomir
источник
2

В случае, если PAGE CONTROL для обозначения текущей страницы - O &&. Вы хотите, чтобы страницы перемещались с помощью прокрутки, а также путем нажатия пользовательских кнопок в 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;}
Йогеш Лолусаре
источник
Вы разместили почти одинаковый ответ на четыре вопроса. Если вы думаете, что один из них является дубликатом другого, вы должны пометить их как таковые (и не публиковать один и тот же ответ несколько раз).
Яап
Так что я могу опубликовать ссылку на этот вопрос над другим аналогичным вопросом, но решение такое же.
Йогеш Лолусаре
1
Я не хочу судить или что-то в этом роде, но форматирование вашего кода мне очень неприятно.
Лукас Петр
1
Прямо @Lukas, я буду форматировать это прямо сейчас. Спасибо
Йогеш Лолусаре
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];

}

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

[self moveToPage];

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

D.Garcia
источник
1

Для одной страницы я только что отредактировал ответ @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

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

setViewControllers:array

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

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

wolffan
источник
0

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

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

Я переписал метод init модели, чтобы передать раскадровку и 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];
}

Обратите внимание, что мне не нужно искать индексы VC, моя кнопка переводит меня на второй VC, но не сложно получить все индексы и отслеживать ваши дочерние представления:

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

Я надеюсь, что это поможет вам!

Томас Калмон
источник
0

Вот решение с использованием методов 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) отправителя ), вы можете программно перейти к следующему или предыдущему контроллеру с помощью UIPageViewControllerDataSouce методов pageViewController: viewControllerBeforeViewController: , pageViewController: viewControllerAfterViewController: чтобы получить следующий или предыдущий вид контроллера и перейдите к нему, вызвав [self.pageViewController setViewControllers: @ [vc] direction: UIPageViewControllerNavigationDirectionForward animated: YES завершение: 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
источник
Подробное объяснение было бы очень полезно.
Таслим Осени
@TaslimOseni спасибо за указание, что пример не был достаточно ясен. Я добавил описание того, как это работает, пожалуйста, дайте мне знать, если вам нужно больше объяснений.
pconor
0

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

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

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

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

parent.SetViewControllers(new UIViewController[] { next }, UIPageViewControllerNavigationDirection.Forward, true, null);
Грант К
источник