UIPageViewController: restituisce la visualizzazione visibile corrente


89

Come fai a sapere qual è la pagina / visualizzazione corrente visualizzata all'interno di un file UIPageViewController ?

Ho sovrascritto il viewDidAppearmetodo delle visualizzazioni di mio figlio, in modo che inviino un ID alla visualizzazione genitore nel loro fileviewDidAppear metodo.

Tuttavia, il problema è questo: non posso utilizzare in modo affidabile quell'ID come ID per la pagina visualizzata. perché se l'utente gira la pagina ma decide a metà di fermare il giro e rimettere la pagina, viewDidAppearsarà già stato chiamato. (la vista è visibile dietro la pagina arricciata).

Forse dovrei passare a un nuovo ID solo se la visualizzazione corrente scompare. Ma mi chiedo se non esista un modo più semplice per restituire la vista attualmente visibile?


Hai provato a usare viewDidAppear:animated:invece?
Fino al

O si. L'ho usato. Ho modificato la domanda per correggere il mio errore.
Jan

Il modo in cui hai modificato la domanda non ha senso per me. O si invia quell'ID da viewWillAppear o da viewDidAppear. Si prega di ricontrollare la modifica.
Fino al

Scusa, ho fatto un pessimo lavoro modificando la domanda. Ho sempre usato viewDidAppear. Spero che la mia ultima modifica lo chiarisca.
Jan

Date un'occhiata a qui ragazzi, questo funziona per me stackoverflow.com/a/36860663/4286947~~V~~plural~~3rd
TheDC

Risposte:


103

È necessario tenere traccia manualmente della pagina corrente. Il metodo delegato pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:ti dirà quando aggiornare quella variabile. L'ultimo argomento del metodo transitionCompleted:può dirti se un utente ha completato o meno una transizione per voltare pagina.


1
+1 per la risposta corretta - Vorrei avere la possibilità di lavorare con UIPageViewController e supportare solo iOS5.
Fino al

Grazie, questa è esattamente la soluzione pulita che stavo cercando. meglio dei delegati sulle pagine.
Jan

3
Quando ruoti il ​​dispositivo, come tieni traccia della pagina corrente?
Satyam

@fino a che puoi, imposta la versione minima del tuo progetto su ios5.0
mtmurdock

83
Come puoi sapere se aumentare o diminuire il numero di pagina corrente?
spessore

59

A partire da iOS 6 ho scoperto che la viewControllersproprietà di UIPageViewController si aggiorna costantemente in modo che manterrà sempre l'unico controller di visualizzazione che rappresenta la pagina corrente e nient'altro. Pertanto, puoi accedere alla pagina corrente chiamando viewControllers[0](supponendo che tu mostri solo un controller di visualizzazione alla volta).

L'array viewController si aggiorna solo una volta che la pagina "si blocca" in posizione, quindi se un utente decide di rivelare parzialmente la pagina successiva, questa non diventa la pagina "corrente" a meno che non completi la transizione.

Se si desidera tenere traccia dei "numeri di pagina", assegnare ai controller di visualizzazione un valore di indice man mano che vengono creati tramite i metodi dell'origine dati di UIPageViewController.


Quindi per esempio:

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

Ma nota i commenti che questo è inaffidabile.


2
L'ho trovato inaffidabile. Non sono riuscito a trovare l'origine del problema. Quando l'animazione termina, accedo alla viewControllersproprietà e ottengo i controller di visualizzazione corretti, ma quando ruoto, sul metodo spineLocationForInterfaceOrientation, non ottengo più i controller di visualizzazione corretti. Quindi ho continuato a mantenere la mia proprietà currentPage invece di fare sempre affidamento sul file viewControllers.
Fábio Oliveira

Interessante, ci giocherò un po 'per vedere come si comporta in questi casi speciali
Eddy Borja

2
Ho anche trovato inaffidabile. Sembra che Apple chiami solo viewControllerBeforeViewController o viewControllerAfterViewController per ogni turno di pagina, ma non aggiorna UIPageViewController.viewControllers. Non so come facciano a riuscire a sbagliare questo tipo di cose, ma lo fanno. Aumenta davvero il mio carico di lavoro e rompe la chiarezza del mio codice (spesso violando DRY e altri principi).
Zack Morris,

3
@ZackMorris. È assolutamente incredibile, hai ragione. È un "momento horror di Apple". Perché oh perché non dovrebbero includere le funzioni ovvie come spostarne uno a destra, su quale pagina sono attualmente, ecc. Ecc. È abbastanza incredibile che non puoi "ottenere la pagina in cui ti trovi !!!"
Fattie

1
self.viewControllers [0] sembra funzionare bene per me. Ma ho chiamato setViewControllers solo una volta durante l'avvio e ho lasciato il resto all'automazione. (testato in iOS 8.4)
Bob

45

Sfortunatamente, tutti i metodi sopra non mi hanno aiutato. Tuttavia, ho trovato la soluzione utilizzando i tag. Potrebbe non essere il migliore, ma funziona e spero che aiuti qualcuno:

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

In Swift: (grazie 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
}

Esempio: gist


3
Questo sembra il più semplice e ha funzionato bene per me. Ho impostato i tag sull'aggiunta dei controller di visualizzazione (ad esempio, HelpPage1ViewController * page1 = [self.storyboard instantiateViewControllerWithIdentifier: @ "page1"]; page1.view.tag = 0;). Quindi puoi impostare una proprietà currentPage per il viewcontroller principale per tenere traccia di dove ti trovi. Assicurati di aggiungere entrambi i protocolli ("<UIPageViewControllerDataSource, UIPageViewControllerDelegate>"), non solo l'origine dati, e imposta il delegato su self ("self.pageViewController.delegate = self;") altrimenti il ​​metodo non verrà chiamato. Questo mi ha sconcertato per un po '.
James Toomey

1
@VictorM questa soluzione non funziona per me. Ho un pageViewController con immagini diverse. Continua a restituire il tag 0 per ogni colpo, qualche idea del perché questo accade? Grazie in anticipo
theDC

1
@VictorM ho passato diversi giorni a provare a salvare l'indice, ma ho trovato accidentalmente questa risposta, vorrei poter votare 1000 volte, grazie!
Evgeniy Kleban

1
Ottima soluzione Grazie speso ore cercando di aggirare questo
Vision Mkhabela

Restituisce solo un valore di 0. Sto facendo qualcosa di sbagliato
N. Der

35

Basandosi sulla risposta di Ole ...

Ecco come ho implementato i 4 metodi per tracciare la pagina corrente e aggiornare l'indicatore di pagina all'indice corretto:

- (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
Penso che l'ultima riga dovrebbe essere self.nextIndex = self.currentIndexpiuttosto che self.nextIndex = 0per ripristinare correttamente l'indice quando una transizione non è completata. Altrimenti rischi di finire con un currentIndexvalore di 0 quando scorri rapidamente avanti e indietro da qualche parte nel mezzo delle tue pagine.
hverlind

1
Questo non funziona completamente per me. A volte, pageViewController: willTransitionToViewControllers non viene chiamato e quindi nextIndex non viene modificato e l'indice corrente è sbagliato.
Hayden Holligan,

31

La soluzione di seguito ha funzionato per me.

Apple potrebbe evitare molti problemi rendendo più configurabile l'impaginazione della visualizzazione a scorrimento UIPageViewController nativa. Ho dovuto ricorrere alla sovrapposizione di un nuovo UIView e UIPageControl solo perché l'impaginazione UIPageViewController nativa non supporta uno sfondo trasparente o il riposizionamento all'interno del frame della visualizzazione.

- (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
in questo cosa intendi per indice?
Yohan

Sto ottenendo l'indice (cioè, il numero intero che rappresenta la posizione del controller di visualizzazione corrente nell'array di self.pageViewController.viewControllers) e quindi lo uso per impostare l'attributo currentPage di self.pageControl (che si aspetta un valore intero) . Ha senso?
sirvine

6
index è una proprietà personalizzata qui credo
Adam Johns

il problema con questo è che se vuoi cambiare pagina senza il metodo di animazione non verrà chiamato
Silviu St

19

Swift 4

Nessun codice non necessario. 3 modi per farlo. Utilizzo del metodo 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
    }
}

Grazie Dio! Non lo sapevo pageViewController.viewControllers. Come fai a conoscere i viewControllers? Il primo è quello in questione?
Script Kitty

Abbastanza semplice in realtà, l'array viewControllers contiene solo il controller di visualizzazione attualmente presentato.
Nikola Milicevic

2
come accedo alla variabile indice da quella funzione?
N. Der

11

Sto tenendo traccia dell'indice della pagina utilizzando una piccola funzione e specificando pageIndex come NSInteger statico.

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

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

e chiamando [self setPageIndex];all'interno della funzione specificata da Ole e anche dopo aver rilevato il cambiamento di orientamento.


5

Ho usato per la prima volta la soluzione di Corey ma non funzionava su iOS5, quindi ho finito per usare,

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

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

Ha provato a passare da una pagina all'altra e per ora funziona bene.


3

Purtroppo niente di cui sopra funziona per me.

Ho due controller di visualizzazione e quando scorro leggermente (circa 20px) l'ultima vista all'indietro, si attiva il delegato:

pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:

e dicendo che la pagina corrente (indice) 0è sbagliata.

Utilizzando delegate all'interno di child viewController qualcosa del tipo:

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

// and a property

@property (nonatomic) NSInteger index;

che viene attivato all'interno viewDidAppearcome:

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

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

Ha funzionato per me.


3

Questo funziona in modo affidabile per me

Ho un UIPageController personalizzato. Questa paginaController.currentPage viene aggiornata dall'UIViewController visualizzato nella visualizzazioneWillAppear

   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
      }

1

Lo uso view.tagda un po 'di tempo, cercare di tenere traccia della pagina corrente era troppo complicato.

In questo codice l'indice è memorizzato all'interno della tagproprietà di ciascuno viewe viene utilizzato per recuperare il VC successivo o precedente. Utilizzando questo metodo è anche possibile creare uno scroll infinito. Controlla il commento nel codice per visualizzare anche questa soluzione:

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

Grazie per la risposta ragazzi, ho affrontato un problema simile, ho dovuto memorizzare l'indice. Modifico leggermente il mio codice, incollalo di seguito:

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

Di seguito il codice demo (in Swift 2) che dimostra come farlo implementando un semplice tutorial di swiper di immagini. Commenti nel codice stesso:

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
    }

}

0

Ho un array viewControllers, che visualizzo in 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
}
}

Cosa importante da notare qui è che il setViewControllers metodo UIPageViewController non fornisce alcuna callback delegato. I callback delegati rappresentano solo le azioni di tocco dell'utente in UIPageViewController .


0

Questa è la soluzione che ho trovato:

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

Utilizzo:

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

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

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

Assicurati di impostare il titolo iniziale


0

Il modo più semplice per avvicinarsi a questo IMHO è utilizzare PageControl per memorizzare il potenziale risultato della transizione e quindi ripristinare se la transizione è stata annullata. Ciò significa che il controllo della pagina cambia non appena l'utente inizia a scorrere, il che per me va bene. Ciò richiede che tu abbia il tuo array di UIViewControllers (in questo esempio chiamato 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

Che ne dici di chiedere un viewControllerdirettamente dalla UIPageViewController(versione Swift 4):

fileprivate weak var currentlyPresentedVC: UIViewController?

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

Oppure, se hai solo bisogno del controller di visualizzazione attualmente presentato in un determinato momento, usa semplicemente pageViewController.viewControllers?.firstin quel momento.


0

In swift 5 e seguenti sirvine rispondono

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
        }

    }

} 

In questo caso non mi interessa quale classe di UIViewController sia incorporata


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

Restituirà l'indice della pagina corrente. e deve usare questo codice sotto la funzione delegato di UIPageViewController (didFinishAnimating).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.