UIPageViewController: вернуть текущий видимый вид

89

Как узнать, какая текущая страница / представление отображается внутри UIPageViewController?

Я переопределил viewDidAppearметод моих дочерних представлений, чтобы они отправляли идентификатор родительскому представлению в своем viewDidAppearметоде.

Однако проблема заключается в следующем: я не могу надежно использовать этот идентификатор в качестве идентификатора для отображаемой страницы. потому что, если пользователь переворачивает страницу, но на полпути решает остановить поворот и вернуть страницу, viewDidAppearона уже будет вызвана. (вид виден за загнутой страницей).

Возможно, мне следует переключиться на новый идентификатор только в том случае, если текущее представление исчезнет. Но мне интересно, нет ли более простого способа вернуть вид, который сейчас виден?

Янв
источник
Вы пробовали использовать viewDidAppear:animated:вместо этого?
до
О да. Я использовал это. Я отредактировал вопрос, чтобы исправить свою ошибку.
янв.
То, как вы отредактировали вопрос, не имеет для меня никакого смысла. Либо вы отправляете этот идентификатор из viewWillAppear, либо из viewDidAppear. Пожалуйста, проверьте свое редактирование еще раз.
до
Извините, я плохо отредактировал вопрос. Я все время использовал viewDidAppear. Надеюсь, моя последняя редакция проясняет это.
янв.
Посмотрите здесь, ребята, у меня это работает stackoverflow.com/a/36860663/4286947
theDC

Ответы:

103

Вы должны вручную отслеживать текущую страницу. Метод делегата pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:сообщит вам, когда обновлять эту переменную. Последний аргумент метода transitionCompleted:может сказать вам, выполнил ли пользователь переход по переворачиванию страницы или нет.

Оле Бегеманн
источник
1
+1 за правильный ответ - я хотел бы иметь возможность работать с UIPageViewController и поддерживать только iOS5.
до
Спасибо, это именно то чистое решение, которое я искал. лучше, чем делегаты на страницах.
янв.
3
Когда вы поворачиваете устройство, как вы отслеживаете текущую страницу?
Satyam
@ пока вы можете, просто установите минимальную версию вашего проекта на ios5.0
mtmurdock
84
Как узнать, увеличивать или уменьшать номер текущей страницы?
shim
59

Что касается iOS 6, я обнаружил, что viewControllersсвойство UIPageViewController постоянно обновляется, поэтому оно всегда будет содержать один контроллер представления, представляющий текущую страницу, и ничего больше. Таким образом, вы можете получить доступ к текущей странице, позвонив viewControllers[0](при условии, что вы показываете только один контроллер представления за раз).

Массив viewController обновляется только после того, как страница «фиксируется» на месте, поэтому, если пользователь решает частично открыть следующую страницу, она не становится «текущей» страницей, пока они не завершат переход.

Если вы хотите отслеживать «номера страниц», присвойте вашим контроллерам представления значение индекса по мере их создания с помощью методов источника данных UIPageViewController.


Так например:

-(void)autoAdvance
    {
    UIViewController *currentVC = self.viewControllers[0];
    NSUInteger currentIndex = [myViewControllers indexOfObject:currentVC];

    if ( currentIndex >= (myViewControllers.count-1) ) return;

    [self setViewControllers:@[myViewControllers[ currentIndex+1 ]]
        direction:UIPageViewControllerNavigationDirectionForward
        animated:YES
        completion:nil];
    }
-(NSInteger)presentationIndexForPageViewController:
                         (UIPageViewController *)pageViewController
    {
    // return 0;
    UIViewController *currentVC = self.viewControllers[0];
    NSUInteger currentIndex = [myViewControllers indexOfObject:currentVC];
    return currentIndex;
    }

Но обратите внимание на комментарии, что это ненадежно.

Эдди Борха
источник
2
Я счел это ненадежным. Я не смог найти источник проблемы. Когда анимация завершается, я обращаюсь к viewControllersсвойству и получаю нужные контроллеры представления, но когда я вращаюсь в методе spineLocationForInterfaceOrientation, я больше не получаю правильные контроллеры представления. Поэтому я оставил собственное свойство currentPage вместо того, чтобы всегда полагаться на viewControllers.
Фабио Оливейра,
Интересно, я немного поиграю с ним, чтобы посмотреть, как он ведет себя в этих особых случаях
Эдди Борха
2
Я также счел это ненадежным. Кажется, Apple просто вызывает viewControllerBeforeViewController или viewControllerAfterViewController для каждого поворота страницы, но не обновляет UIPageViewController.viewControllers. Я не знаю, как им удается ошибаться в подобных вещах, но они это делают. Это действительно увеличивает мою рабочую нагрузку и нарушает ясность моего кода (часто нарушая DRY и другие принципы).
Zack Morris
3
@ZackMorris. Совершенно невероятно, вы совершенно правы. Это «момент ужаса Apple». Почему бы им не включить такие очевидные функции, как перемещение на единицу вправо, на какой странице я сейчас и т.д.
Fattie
1
self.viewControllers [0], кажется, мне подходит. Но я просто вызываю setViewControllers один раз во время инициализации, а остальное оставляю автоматизации. (протестировано в iOS 8.4)
Боб
45

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

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed 
{
    if (completed) {
        int currentIndex = ((UIViewController *)self.pageViewController.viewControllers.firstObject).view.tag;
        self.pageControl.currentPage = currentIndex;
    }
}

В Swift: (спасибо @Jessy )

func pageViewController(pageViewController: UIPageViewController,
    didFinishAnimating finished: Bool,
    previousViewControllers: [UIViewController],
    transitionCompleted completed: Bool)
{
    guard completed else { return }
    self.pageControl.currentPage = pageViewController.viewControllers!.first!.view.tag
}

Пример: суть

Виктор
источник
3
Это кажется наиболее простым и хорошо сработало для меня. Я установил теги при добавлении контроллеров представления (например, HelpPage1ViewController * page1 = [self.storyboard instantiateViewControllerWithIdentifier: @ "page1"]; page1.view.tag = 0;). Затем вы можете установить свойство currentPage для главного контроллера просмотра, чтобы отслеживать, где вы находитесь. Обязательно добавьте оба протокола («<UIPageViewControllerDataSource, UIPageViewControllerDelegate>»), а не только источник данных, и установите для делегата значение «self» («self.pageViewController.delegate = self;»), иначе метод не будет вызываться. Это немного сбило меня с толку.
Джеймс Туми
1
@VictorM это решение не работает для меня. У меня есть pageViewController с разными изображениями. Он продолжает возвращать тег 0 для каждого удара, есть идеи, почему это происходит? Заранее спасибо
theDC
1
@VictorM Я потратил несколько дней, пытаясь сохранить индекс, но случайно нашел этот ответ, я бы хотел проголосовать 1000 раз, спасибо!
Евгений Клебан
1
Отличное решение Спасибо, потратили часы, пытаясь обойти это
Vision Mkhabela
Он возвращает только значение 0. Я что-то делаю не так?
N. Der
35

Основываясь на ответе Оле…

Вот как я реализовал 4 метода для отслеживания текущей страницы и обновления индикатора страницы до правильного индекса:

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController{

    return (NSInteger)[self.model count];

}

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController{

    return (NSInteger)self.currentIndex;
}

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

    SJJeanViewController* controller = [pendingViewControllers firstObject];
    self.nextIndex = [self indexOfViewController:controller];

}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{

    if(completed){

        self.currentIndex = self.nextIndex;

    }

    self.nextIndex = 0;

}
Кори Флойд
источник
2
Думаю последняя строчка должна быть self.nextIndex = self.currentIndexа не self.nextIndex = 0для того, чтобы правильно восстанавливать индекс, когда переход не завершен. В противном случае вы рискуете получить currentIndexзначение 0 при быстром перелистывании назад и вперед где-нибудь в середине ваших страниц.
hverlind
1
Для меня это не работает полностью. Иногда pageViewController: willTransitionToViewControllers не вызывается и, следовательно, nextIndex не изменяется, и тогда текущий индекс неверен.
Хайден Холлиган
31

Приведенное ниже решение сработало для меня.

Apple могла бы избежать множества хлопот, сделав нативную разбивку на страницы UIPageViewController более настраиваемой. Мне пришлось прибегнуть к наложению нового UIView и UIPageControl только потому, что нативная разбивка на страницы UIPageViewController не поддерживает прозрачный фон или изменение положения внутри рамки просмотра.

- (void)pageViewController:(UIPageViewController *)pvc didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
  if (!completed)
  {
    return;
  }
  NSUInteger currentIndex = [[self.pageViewController.viewControllers lastObject] index];
  self.pageControl.currentPage = currentIndex;
}
сирвина
источник
1
что вы подразумеваете под индексом?
Йохан
Я получаю индекс (то есть целое число, которое представляет позицию текущего контроллера представления в массиве self.pageViewController.viewControllers), а затем использую его для установки атрибута currentPage для self.pageControl (который ожидает целочисленное значение) . Есть смысл?
sirvine
6
index - это настраиваемое свойство, я считаю,
Адам Джонс
проблема в том, что если вы хотите сменить страницу без анимации, метод не будет вызываться
Silviu St
19

Swift 4

Никакого лишнего кода. 3 способа сделать это. Используя метод UIPageViewControllerDelegate .

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    guard completed else { return }

    // using content viewcontroller's index
    guard let index = (pageViewController.viewControllers?.first as? ContentViewController)?.index else { return }

    // using viewcontroller's view tag
    guard let index = pageViewController.viewControllers?.first?.view.tag else { return }

    // switch on viewcontroller
    guard let vc = pageViewController.viewControllers?.first else { return }
    let index: Int
    switch vc {
    case is FirstViewController:
        index = 0
    case is SecondViewController:
        index = 1
    default:
        index = 2
    }
}
Никола Миличевич
источник
Слава Богу! Я не знал об этом pageViewController.viewControllers. Откуда вы знаете, что viewControllers? .Первый, о котором идет речь?
Script Kitty
На самом деле довольно просто, массив viewControllers содержит только текущий контроллер представления.
Никола Миличевич
2
как мне получить доступ к индексной переменной из этой функции?
N. Der
11

Я отслеживаю индекс страницы, используя небольшую функцию и определяя pageIndex как статический NSInteger.

-(void) setPageIndex
{
    DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];

    pageIndex = [self.modelController indexOfViewController:theCurrentViewController];
}

и вызов [self setPageIndex];внутри функции, указанной Оле, а также после обнаружения изменения ориентации.

Вахиб Уль Хак
источник
5

Сначала я использовал решение Кори, но оно не работало на iOS5, а затем я использовал,

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{

    if(completed) {
        _currentViewController = [pageViewController.viewControllers lastObject];
    }
}

Он пробовал переключаться между разными страницами и пока работает хорошо.

Басит Али
источник
3

К сожалению, у меня ничего не работает.

У меня есть два контроллера представления, и когда я немного (около 20 пикселей) прокручиваю последнее представление назад, он запускает делегата:

pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:

и говорят, что текущая страница (индекс) 0неверна.

Использование делегата внутри дочернего viewController примерно так:

- (void)ViewController:(id)VC didShowWithIndex:(long)page;

// and a property

@property (nonatomic) NSInteger index;

который запускается внутри viewDidAppearкак:

- (void)viewDidAppear:(BOOL)animated
{
    ...

    [self.delegate ViewController:self didShowWithIndex:self.index];
}

Работал у меня.

0yeoj
источник
3

У меня это работает надежно

У меня есть собственный UIPageController. Этот pageController.currentPage обновляется из отображаемого UIViewController в viewWillAppear

   var delegate: PageViewControllerUpdateCurrentPageNumberDelegate?

      init(delegate: PageViewControllerUpdateCurrentPageNumberDelegate ){
        self.delegate = delegate
        super.init(nibName: nil, bundle: nil)
      }

      required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
      }

    override func viewWillAppear(animated: Bool) {

        if delegate != nil {
          self.delegate!.upateCurrentPageNumber(0) //(0) is the pageNumber corresponding to the displayed controller
        }
      } 

    //In the pageViewController 

    protocol PageViewControllerUpdateCurrentPageNumberDelegate {

      func upateCurrentPageNumber(currentPageIndex: Int)
    }

     create the view display controllers initializing with the delegate

    orderedViewControllers = {
              return [
                IntroductionFirstPageViewController(delegate: self),
                IntroductionSecondPageViewController(delegate: self),
                IntroductionThirdPageViewController(delegate: self)
              ]

            }()

    the function implementing the protocol

    func upateCurrentPageNumber(currentPageIndex: Int){
        pageControl.currentPage = currentPageIndex
      }
lguerra10
источник
1

Я уже давно использую view.tag, пытаться отслеживать текущую страницу было слишком сложно.

В этом коде индекс хранится в tagсвойстве каждого viewи используется для выборки следующего или предыдущего VC. С помощью этого метода также можно создать бесконечную прокрутку. Ознакомьтесь с комментарием в коде, чтобы также просмотреть это решение:

extension MyPageViewController: UIPageViewControllerDataSource {

  func viewControllerWithIndex(var index: Int) -> UIViewController! {
    let myViewController = storyboard?.instantiateViewControllerWithIdentifier("MyViewController") as MyViewController

    if let endIndex = records?.endIndex {
      if index < 0 || index >= endIndex { return nil }
      // Instead, We can normalize the index to be cyclical to create infinite scrolling
      // if index < 0 { index += endIndex }
      // index %= endIndex
    }

    myViewController.view.tag = index
    myViewController.record = records?[index]

    return myViewController
  }

  func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
    let index = viewController.view?.tag ?? 0
    return viewControllerWithIndex(index + 1)
  }

  func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
    let index = viewController.view?.tag ?? 0
    return viewControllerWithIndex(index - 1)
  }

  func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
    return records?.count ?? 0
  }

  func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
    return (pageViewController.viewControllers.first as? UIViewController)?.view.tag ?? 0
  }
}
Ярив Нисим
источник
1

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

- (MenuListViewController *)viewControllerAtIndex:(NSInteger)index {

    if (_menues.count < 1)
        return nil;

    //    MenuListViewController *childViewController = [MenuListViewController initWithSecondSetFakeItems];
    MenuListViewController *childViewController = self.menues[index];
    childViewController.index = index;

    return childViewController;
}

#pragma mark - Page View Controller Data Source

- (void)pageViewController:(UIPageViewController *)pageViewController
        didFinishAnimating:(BOOL)finished
   previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers
       transitionCompleted:(BOOL)completed{

    if (completed) {

        NSUInteger currentIndex = ((MenuListViewController *)self.pageController.viewControllers.firstObject).index;
        NSLog(@"index %lu", (unsigned long)currentIndex);
    }
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = [(MenuListViewController *)viewController index];

    if (index == 0)
        return nil;

    index --;

    return [self viewControllerAtIndex:index];
}


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

    NSUInteger index = [(MenuListViewController *)viewController index];

    index ++;

    if (index == _menues.count)
        return nil;

    return [self viewControllerAtIndex:index];
}
Евгений Клебан
источник
0
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {

    NSLog(@"Current Page = %@", pageViewController.viewControllers);

    UIViewController *currentView = [pageViewController.viewControllers objectAtIndex:0];

    if ([currentView isKindOfClass:[FirstPageViewController class]]) {
             NSLog(@"First View");
        }
        else if([currentView isKindOfClass:[SecondPageViewController class]]) {
             NSLog(@"Second View");
        }
        else if([currentView isKindOfClass:[ThirdViewController class]]) {
              NSLog(@"Third View");
        }
}

//pageViewController.viewControllers always return current visible View ViewController
Авинаш
источник
0

Ниже демонстрационный код (в Swift 2), который демонстрирует, как это делается, реализуя простой учебник по перемещению изображений. Комментарии в самом коде:

import UIKit

/*
VCTutorialImagePage represents one page show inside the UIPageViewController.
You should create this page in your interfacebuilder file:
- create a new view controller
- set its class to VCTutorialImagePage
- sets its storyboard identifier to "VCTutorialImagePage" (needed for the loadView function)
- put an imageView on it and set the contraints (I guess to top/bottom/left/right all to zero from the superview)
- connect it to the "imageView" outlet
*/

class VCTutorialImagePage : UIViewController {
    //image to display, configure this in interface builder
    @IBOutlet weak var imageView: UIImageView!
    //index of this page
    var pageIndex : Int = 0

    //loads a new view via the storyboard identifier
    static func loadView(pageIndex : Int, image : UIImage) -> VCTutorialImagePage {
        let storyboard = UIStoryboard(name: storyBoardHome, bundle: nil)
        let vc = storyboard.instantiateViewControllerWithIdentifier("VCTutorialImagePage") as! VCTutorialImagePage
        vc.imageView.image      = image
        vc.pageIndex            = pageIndex
        return vc
    }
}


/*
VCTutorialImageSwiper takes an array of images (= its model) and displays a UIPageViewController 
where each page is a VCTutorialImagePage that displays an image. It lets you swipe throught the 
images and will do a round-robbin : when you swipe past the last image it will jump back to the 
first one (and the other way arround).

In this process, it keeps track of the current displayed page index
*/

class VCTutorialImageSwiper: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    //our model = images we are showing
    let tutorialImages : [UIImage] = [UIImage(named: "image1")!, UIImage(named: "image2")!,UIImage(named: "image3")!,UIImage(named: "image4")!]
    //page currently being viewed
    private var currentPageIndex : Int = 0 {
        didSet {
            currentPageIndex=cap(currentPageIndex)
        }
    }
    //next page index, temp var for keeping track of the current page
    private var nextPageIndex : Int = 0


    //Mark: - life cylce


    override func viewDidLoad() {
        super.viewDidLoad()
        //setup page vc
        dataSource=self
        delegate=self
        setViewControllers([pageForindex(0)!], direction: .Forward, animated: false, completion: nil)
    }


    //Mark: - helper functions

    func cap(pageIndex : Int) -> Int{
        if pageIndex > (tutorialImages.count - 1) {
            return 0
        }
        if pageIndex < 0 {
            return (tutorialImages.count - 1)
        }
        return pageIndex
    }

    func carrouselJump() {
        currentPageIndex++
        setViewControllers([self.pageForindex(currentPageIndex)!], direction: .Forward, animated: true, completion: nil)
    }

    func pageForindex(pageIndex : Int) -> UIViewController? {
        guard (pageIndex < tutorialImages.count) && (pageIndex>=0) else { return nil }
        return VCTutorialImagePage.loadView(pageIndex, image: tutorialImages[pageIndex])
    }

    func indexForPage(vc : UIViewController) -> Int {
        guard let vc = vc as? VCTutorialImagePage else {
            preconditionFailure("VCPagImageSlidesTutorial page is not a VCTutorialImagePage")
        }
        return vc.pageIndex
    }


    //Mark: - UIPageView delegate/datasource


    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        return pageForindex(cap(indexForPage(viewController)+1))
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        return pageForindex(cap(indexForPage(viewController)-1))
    }

    func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) {
        nextPageIndex = indexForPage(pendingViewControllers.first!)
    }

    func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        if !finished { return }
        currentPageIndex = nextPageIndex
    }

    func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
        return tutorialImages.count
    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
        return currentPageIndex
    }

}
HixField
источник
0

У меня есть массив viewControllers, который я отображаю в UIPageViewController .

extension MyViewController: UIPageViewControllerDataSource {

func presentationCount(for pageViewController: UIPageViewController) -> Int {
    return self.viewControllers.count
}

func presentationIndex(for pageViewController: UIPageViewController) -> Int {
    return self.currentPageIndex
}
}




extension MyViewController: UIPageViewControllerDelegate {

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {

    if !completed { return }

    guard let viewController = previousViewControllers.last, let index = indexOf(viewController: viewController) else {
        return
    }

    self.currentPageIndex = index

}

fileprivate func indexOf(viewController: UIViewController) -> Int? {
    let index = self.viewControllers.index(of: viewController)
    return index
}
}

Важно отметить здесь, что setViewControllers метод UIPageViewController не дает какой - либо делегат обратного вызова. Обратные вызовы делегатов представляют только действия пользователя касания в UIPageViewController .

Jarora
источник
0

Это решение, которое я придумал:

class DefaultUIPageViewControllerDelegate: NSObject, UIPageViewControllerDelegate {

    // MARK: Public values
    var didTransitionToViewControllerCallback: ((UIViewController) -> Void)?

    // MARK: Private values
    private var viewControllerToTransitionTo: UIViewController!

    // MARK: Methods
    func pageViewController(
        _ pageViewController: UIPageViewController,
        willTransitionTo pendingViewControllers: [UIViewController]
    ) {
        viewControllerToTransitionTo = pendingViewControllers.last!
    }

    func pageViewController(
        _ pageViewController: UIPageViewController,
        didFinishAnimating finished: Bool,
        previousViewControllers: [UIViewController],
        transitionCompleted completed: Bool
    ) {
        didTransitionToViewControllerCallback?(viewControllerToTransitionTo)
    }
}

Применение:

 let pageViewController = UIPageViewController()
 let delegate = DefaultUIPageViewControllerDelegate()

 delegate.didTransitionToViewControllerCallback = {
    pageViewController.title = $0.title
 }

 pageViewController.title = viewControllers.first?.title
 pageViewController.delegate = delegate

Не забудьте установить начальный заголовок

Питер Комби
источник
0

Самый простой способ приблизиться к этому IMHO - использовать PageControl для хранения потенциального результата перехода, а затем вернуться, если переход был отменен. Это означает, что элемент управления страницей изменяется, как только пользователь начинает пролистывать, что меня устраивает. Для этого требуется, чтобы у вас был собственный массив UIViewControllers (в этом примере называется allViewControllers)

func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
    if let index = self.allViewControllers.index(of: pendingViewControllers[0]) {
        self.pageControl.currentPage = index
    }
}

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    if !completed, let previousIndex = self.allViewControllers.index(of: previousViewControllers[0]) {
        self.pageControl.currentPage = previousIndex
    }
}
Свифт Тейлор
источник
0

Как насчет того, чтобы запросить viewControllerпрямо из UIPageViewController(версия Swift 4):

fileprivate weak var currentlyPresentedVC: UIViewController?

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    currentlyPresentedVC = pageViewController.viewControllers?.first
}

Или, если вам просто нужен текущий контроллер представления в какой-то момент времени, просто используйте pageViewController.viewControllers?.firstв это время.

Милан Носань
источник
0

В быстром 5 и следующем ответе sirvine

extension InnerDetailViewController: UIPageViewControllerDelegate {

    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {

        if completed {
            guard let newIndex = embeddedViewControllers.firstIndex(where: { $0 == pageViewController.viewControllers?.last }) else { return }
            print(newIndex)
            currentEmbeddedViewControllerIndex = newIndex
        }

    }

} 

В этом случае мне все равно, какой класс UIViewController встроен

Реймонд Хилл
источник
-1
UIViewController *viewController = [pageViewController.viewControllers objectAtIndex:0];
NSUInteger currentIndex = [(ViewController*) viewController indexNumber];

Он вернет текущий индекс страницы. и должен использовать этот код в функции делегата UIPageViewController (didFinishAnimating).

Винай Подили
источник