UIPageViewController: retorna a visão visível atual

89

Como você sabe qual é a página / visualização atual exibida dentro de um UIPageViewController?

Eu substituí o viewDidAppearmétodo de minhas visualizações filhas, para que eles enviem um id para a visualização pai em seu viewDidAppearmétodo.

No entanto, o problema é o seguinte: não consigo usar esse id como id para a página exibida de forma confiável. porque se o usuário virar a página, mas na metade decidir parar de virar e colocar a página de volta, viewDidAppearjá terá sido chamado. (a visualização é visível atrás da página enrolada).

Talvez eu só deva mudar para um novo id se a visão atual desaparecer. Mas será que não existe uma maneira mais simples de retornar a vista que está visível atualmente?

Jan
fonte
Você já tentou usar viewDidAppear:animated:?
Até
Oh, sim. Eu usei isso. Editei a pergunta para corrigir meu erro.
janeiro
A maneira como você editou a pergunta não faz sentido para mim. Você pode enviar esse id de viewWillAppear ou de viewDidAppear. Verifique novamente sua edição.
Até
Desculpe, eu fiz um péssimo trabalho ao editar a pergunta. Usei viewDidAppear o tempo todo. Espero que minha última edição esclareça isso.
janeiro
Dê uma olhada aqui, pessoal, isso funciona para mim stackoverflow.com/a/36860663/4286947
theDC

Respostas:

103

Você deve controlar manualmente a página atual. O método delegado pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:dirá quando atualizar essa variável. O último argumento do método transitionCompleted:pode informar se um usuário concluiu uma transição de virada de página ou não.

Ole Begemann
fonte
1
+1 para a resposta correta - Eu gostaria de ter a chance de trabalhar com UIPageViewController e suportar apenas iOS5.
Até
Obrigado, essa é exatamente a solução limpa que eu estava procurando. melhor do que delegados nas páginas.
janeiro
3
Quando você gira o dispositivo, como você controla a página atual?
Satyam
@até você pode, basta definir a versão mínima do seu projeto para ios5.0
mtmurdock
83
Como você pode saber se deve aumentar ou diminuir o número da página atual?
shim
59

No iOS 6, descobri que a viewControllerspropriedade de UIPageViewController é atualizada constantemente para que sempre mantenha o controlador de visualização que representa a página atual e nada mais. Assim, você pode acessar a página atual chamando viewControllers[0](assumindo que você mostre apenas um controlador de visualização por vez).

O array viewController é atualizado apenas quando a página "bloqueia" no lugar, portanto, se um usuário decidir revelar parcialmente a próxima página, ela não se tornará a página "atual" a menos que conclua a transição.

Se você quiser acompanhar os "números de página", atribua aos seus controladores de visualização um valor de índice conforme você os cria através dos métodos de fonte de dados UIPageViewController.


Então, por exemplo:

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

Mas observe os comentários de que isso não é confiável.

Eddy Borja
fonte
2
Eu achei que não era confiável. Não consegui encontrar a origem do problema. Quando a animação termina, eu acesso a viewControllerspropriedade e obtenho os controladores de vista corretos, mas quando giro, no método spineLocationForInterfaceOrientation, não consigo mais os controladores de vista corretos. Portanto, mantive minha própria propriedade currentPage em vez de depender sempre do viewControllers.
Fábio Oliveira
Interessante, vou brincar um pouco para ver como se comporta nesses casos especiais
Eddy Borja
2
Eu também achei que não era confiável. Parece que a Apple apenas chama viewControllerBeforeViewController ou viewControllerAfterViewController para cada virada de página, mas não atualiza UIPageViewController.viewControllers. Não sei como eles conseguem fazer esse tipo de coisa errado, mas eles conseguem. Isso realmente aumenta minha carga de trabalho e quebra a clareza do meu código (muitas vezes violando o DRY e outros princípios).
Zack Morris
3
@ZackMorris. É absolutamente incrível, você está certo. É um "momento de terror da Apple". Por que, ah, por que eles não incluiriam as funções óbvias, como mover um para a direita, em que página estou atualmente, etc. etc. É incrível que você não possa "obter a página em que está !!!"
Fattie
1
self.viewControllers [0] parece funcionar bem para mim. Mas eu apenas chamo setViewControllers uma vez durante a iniciação e deixo o resto para a automação. (testado em iOS 8.4)
Bob
45

Infelizmente, todos os métodos acima não me ajudaram. No entanto, encontrei a solução usando tags. Pode ser que não seja o melhor, mas funciona e espero que ajude alguém:

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

Em Swift: (obrigado a @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
}

Exemplo: essência

Vencedor
fonte
3
Isso parece o mais simples e funcionou bem para mim. Eu defino as tags ao adicionar os controladores de visualização (por exemplo, HelpPage1ViewController * page1 = [self.storyboard instantiateViewControllerWithIdentifier: @ "page1"]; page1.view.tag = 0;). Em seguida, você pode definir uma propriedade currentPage para o controlador de exibição mestre para manter o controle de onde você está. Certifique-se de adicionar os dois protocolos ("<UIPageViewControllerDataSource, UIPageViewControllerDelegate>"), não apenas a fonte de dados, e definir o delegado para self ("self.pageViewController.delegate = self;") ou o método não será chamado. Isso me confundiu um pouco.
James Toomey
1
@VictorM esta solução não funciona para mim. Eu tenho um pageViewController com imagens diferentes. Ele continua retornando a tag 0 a cada furto, alguma ideia de por que isso acontece? Agradecemos antecipadamente
theDC
1
@VictorM Passei vários dias tentando salvar o índice, mas acidentalmente encontrei esta resposta, gostaria de poder votar a favor 1000 vezes, obrigado!
Evgeniy Kleban
1
Ótima solução. Obrigado por horas tentando contornar isso
Visão Mkhabela
Ele retorna apenas um valor de 0. Estou fazendo algo errado
N. Der
35

Com base na resposta de Ole ...

É assim que implementei os 4 métodos para rastrear a página atual e atualizar o indicador da página para o índice correto:

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

}
Corey Floyd
fonte
2
Acho que a última linha deve ser em self.nextIndex = self.currentIndexvez de self.nextIndex = 0restaurar o índice corretamente quando uma transição não for concluída. Caso contrário, você corre o risco de acabar com um currentIndexvalor 0 ao paginar rapidamente para frente e para trás em algum lugar no meio de suas páginas.
hverlind
1
Isso não funciona totalmente para mim. Às vezes, pageViewController: willTransitionToViewControllers não é chamado e, portanto, nextIndex não é alterado e o índice atual está errado.
Hayden Holligan
31

A solução abaixo funcionou para mim.

A Apple poderia evitar muitos problemas tornando a paginação da visualização de rolagem UIPageViewController mais configurável. Tive que recorrer à sobreposição de um novo UIView e UIPageControl apenas porque a paginação UIPageViewController nativa não suporta um fundo transparente ou reposicionamento dentro do quadro de exibição.

- (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;
}
Sirvine
fonte
1
nisso o que você quer dizer com índice?
Yohan de
Estou obtendo o índice (ou seja, o inteiro que representa a posição do controlador de exibição atual na matriz de self.pageViewController.viewControllers) e, em seguida, usando isso para definir o atributo currentPage de self.pageControl (que espera um valor inteiro) . Faz sentido?
sirvine
6
o índice é uma propriedade personalizada aqui, eu acredito
Adam Johns
problema com isso é que se você quiser mudar a página sem o método de animação não será chamado
Silviu St
19

Swift 4

Nenhum código desnecessário. 3 maneiras de fazer isso. Usando o método 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
    }
}
Nikola Milicevic
fonte
Graças a Deus! Eu não sabia sobre pageViewController.viewControllers. Como você conhece viewControllers? .First é o que está em questão?
Script Kitty
Muito simples, na verdade, o array viewControllers contém apenas o controlador de visualização apresentado atualmente.
Nikola Milicevic
2
como faço para acessar a variável de índice fora dessa função?
N. Der
11

Estou acompanhando o índice da página usando uma pequena função e especificando pageIndex como NSInteger estático.

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

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

e chamar [self setPageIndex];dentro da função especificada por Ole e também depois de detectar a mudança na orientação.

Wahib Ul Haq
fonte
5

Usei a solução do Corey pela primeira vez, mas não estava funcionando no iOS5, então acabei usando,

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

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

Ele tentou alternar entre páginas diferentes e funciona bem por enquanto.

Basit Ali
fonte
3

Infelizmente, nada acima funciona para mim.

Eu tenho dois controladores de visualização e quando eu levemente (cerca de 20px) rolar a última visualização para trás, ele aciona o delegado:

pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:

e dizendo que a página atual (índice) é 0 está errada.

Usando delegate dentro do viewController filho, algo como:

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

// and a property

@property (nonatomic) NSInteger index;

que é acionado internamente viewDidAppearcomo:

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

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

Funcionou para mim.

0yeoj
fonte
3

Isso funciona para mim de forma confiável

Eu tenho um UIPageController personalizado. Esta pageController.currentPage é atualizada a partir do UIViewController exibido no 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
fonte
1

Tenho usado view.tag por um tempo agora, tentar manter o controle da página atual era muito complicado.

Neste código, o índice é armazenado dentro da tagpropriedade de cada um viewe é usado para buscar o próximo VC ou o anterior. Usando este método também é possível criar um pergaminho infinito. Confira o comentário no código para visualizar esta solução também:

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
  }
}
Yariv Nissim
fonte
1

Obrigado pela sua resposta pessoal, enfrentei problema semelhante, tive que armazenar o índice. Eu modifico ligeiramente meu código, colo-o abaixo:

- (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];
}
Evgeniy Kleban
fonte
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
Avinash
fonte
0

Abaixo, o código de demonstração (em Swift 2) que demonstra como isso é feito implementando um tutorial simples de swiper de imagem. Comentários no próprio código:

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
fonte
0

Eu tenho uma matriz viewControllers, que exibo no 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
}
}

Coisa importante a notar aqui é que o setViewControllers método de UIPageViewController não dá qualquer retorno de chamada delegado. Os retornos de chamada delegados representam apenas ações de toque do usuário no UIPageViewController .

Jarora
fonte
0

Esta é a solução que encontrei:

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

Uso:

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

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

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

Certifique-se de definir o título inicial

Peter Combee
fonte
0

A maneira mais simples de abordar este IMHO é usar o PageControl para armazenar o resultado potencial da transição e, em seguida, reverter se a transição foi cancelada. Isso significa que o controle da página muda assim que o usuário começa a deslizar, o que está ok para mim. Isso requer que você tenha seu próprio array de UIViewControllers (neste exemplo, chamado 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
    }
}
taylor rápido
fonte
0

Que tal pedir um viewControllerdiretamente do UIPageViewController(versão Swift 4):

fileprivate weak var currentlyPresentedVC: UIViewController?

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

Ou, se você só precisa do controlador de visualização apresentado atualmente em algum ponto do tempo, simplesmente use pageViewController.viewControllers?.firstnesse momento.

Milan Nosáľ
fonte
0

No swift 5 e seguinte resposta 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
        }

    }

} 

Neste caso, eu não me importo com qual classe de UIViewController está embutida

Reimond Hill
fonte
-1
UIViewController *viewController = [pageViewController.viewControllers objectAtIndex:0];
NSUInteger currentIndex = [(ViewController*) viewController indexNumber];

Ele retornará o índice da página atual. e deve usar este código sob a função de delegado de UIPageViewController (didFinishAnimating).

Vinay Podili
fonte