UIPageViewController: mengembalikan tampilan yang terlihat saat ini

89

Bagaimana Anda tahu apa yang ditampilkan halaman / tampilan saat ini di dalam UIPageViewController?

Saya telah mengganti viewDidAppearmetode tampilan anak saya, sehingga mereka mengirim id ke tampilan induk dalam viewDidAppearmetode mereka .

Namun, masalahnya adalah ini: saya tidak dapat menggunakan id itu sebagai id untuk halaman yang ditampilkan. karena jika pengguna membalik halaman tetapi setengah jalan memutuskan untuk berhenti membalik dan mengembalikan halaman, viewDidAppearakan sudah dipanggil. (tampilan terlihat di belakang halaman yang digulung).

Mungkin saya hanya harus beralih ke id baru jika tampilan saat ini menghilang. Tetapi saya bertanya-tanya apakah tidak ada cara yang lebih sederhana untuk mengembalikan tampilan yang saat ini terlihat?

Jan
sumber
Sudahkah Anda mencoba menggunakan viewDidAppear:animated:?
Hingga
O ya. Saya memang menggunakan itu. Saya mengedit pertanyaan untuk memperbaiki kesalahan saya.
Jan
Cara Anda mengedit pertanyaan tidak masuk akal bagi saya. Entah Anda mengirim id tersebut dari dalam viewWillAppear atau dari viewDidAppear. Harap periksa kembali hasil edit Anda.
Hingga
Maaf, saya melakukan pekerjaan yang buruk saat mengedit pertanyaan. Saya menggunakan viewDidAppear selama ini. Saya harap hasil edit terakhir saya menjelaskan hal itu.
Jan
Lihatlah di sini teman-teman, ini bekerja untuk saya stackoverflow.com/a/36860663/4286947
theDC

Jawaban:

103

Anda harus melacak halaman ini secara manual. Metode delegasi pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:akan memberi tahu Anda kapan harus memperbarui variabel itu. Argumen terakhir dari metode ini transitionCompleted:dapat memberi tahu Anda apakah pengguna menyelesaikan transisi pergantian halaman atau tidak.

Ole Begemann
sumber
1
1 untuk jawaban yang benar - Saya berharap saya memiliki kesempatan untuk bekerja dengan UIPageViewController dan hanya mendukung iOS5.
Hingga
Terima kasih, itulah solusi bersih yang saya cari. lebih baik daripada delegasi di halaman.
Jan
3
Saat Anda memutar perangkat, bagaimana Anda melacak halaman saat ini?
Satyam
@sampai Anda bisa, cukup setel versi min proyek Anda ke ios5.0
mtmurdock
84
Bagaimana Anda bisa tahu apakah akan menaikkan atau menurunkan nomor halaman saat ini?
shim
59

Mulai iOS 6, saya telah menemukan bahwa viewControllersproperti UIPageViewController terus diperbarui sehingga akan selalu memegang satu pengontrol tampilan yang mewakili halaman saat ini, dan tidak ada yang lain. Dengan demikian, Anda dapat mengakses halaman saat ini dengan memanggil viewControllers[0](Dengan asumsi Anda hanya menampilkan satu pengontrol tampilan dalam satu waktu).

Larik viewController hanya memperbarui setelah halaman "terkunci" pada tempatnya, jadi jika pengguna memutuskan untuk menampilkan sebagian halaman berikutnya, halaman tersebut tidak menjadi halaman "saat ini" kecuali mereka menyelesaikan transisi.

Jika Anda ingin terus melacak "nomor halaman", tetapkan pengontrol tampilan Anda nilai indeks saat Anda membuatnya melalui metode sumber data UIPageViewController.


Jadi contohnya:

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

Tapi perhatikan komentar bahwa ini tidak bisa diandalkan.

Eddy Borja
sumber
2
Saya merasa tidak bisa diandalkan. Saya tidak dapat menemukan sumber masalahnya. Ketika animasi selesai saya mengakses viewControllersproperti dan saya mendapatkan pengontrol tampilan yang benar tetapi ketika saya memutar, pada metode spineLocationForInterfaceOrientation, saya tidak mendapatkan pengontrol tampilan yang benar lagi. Jadi saya tetap mempertahankan properti currentPage saya sendiri alih-alih selalu mengandalkan viewControllers.
Fábio Oliveira
Menarik, saya akan bermain dengannya sedikit untuk melihat bagaimana perilakunya dalam kasus khusus ini
Eddy Borja
2
Saya juga merasa tidak bisa diandalkan. Tampaknya Apple hanya memanggil viewControllerBeforeViewController atau viewControllerAfterViewController untuk setiap pembalikan halaman, tetapi tidak memperbarui UIPageViewController.viewControllers. Saya tidak tahu bagaimana mereka terus berusaha melakukan kesalahan seperti ini, tetapi mereka melakukannya. Ini benar-benar meningkatkan beban kerja saya, dan merusak kejelasan kode saya (sering melanggar KERING dan prinsip lainnya).
Zack Morris
3
@Tokopedia Ini benar-benar luar biasa, Anda benar. Ini adalah "momen horor Apple". Mengapa oh mengapa mereka tidak menyertakan fungsi yang jelas seperti memindahkan satu ke kanan, halaman apa yang saya buka saat ini, dll. Cukup luar biasa Anda tidak bisa "mendapatkan halaman yang Anda buka !!!"
Fattie
1
self.viewControllers [0] tampaknya berfungsi dengan baik untuk saya. Tapi saya hanya memanggil setViewControllers sekali selama inisiasi dan membiarkan sisanya untuk otomatisasi. (diuji di iOS 8.4)
Bob
45

Sayangnya, semua metode di atas tidak membantu saya. Namun demikian, saya telah menemukan solusinya dengan menggunakan tag. Mungkin ini bukan yang terbaik, tetapi berhasil dan berharap ini membantu seseorang:

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

Di Swift: (terima kasih kepada @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
}

Contoh: inti

Pemenang
sumber
3
Ini sepertinya yang paling mudah dan berhasil bagi saya. Saya menyetel tag untuk menambahkan pengontrol tampilan (misalnya, HelpPage1ViewController * page1 = [self.storyboard instantiateViewControllerWithIdentifier: @ "page1"]; page1.view.tag = 0;). Kemudian Anda dapat menyetel properti currentPage untuk master viewcontroller untuk melacak di mana Anda berada. Pastikan untuk menambahkan kedua protokol ("<UIPageViewControllerDataSource, UIPageViewControllerDelegate>"), bukan hanya sumber data, dan setel delegasi ke self ("self.pageViewController.delegate = self;") atau metode tidak akan dipanggil. Ini sedikit membingungkan saya.
James Toomey
1
@VictorM solusi ini tidak bekerja untuk saya. Saya memiliki pageViewController dengan gambar yang berbeda. Itu terus mengembalikan tag 0 untuk setiap gesekan, tahu mengapa ini terjadi? Terima kasih sebelumnya
theDC
1
@VictorM Saya menghabiskan beberapa hari mencoba untuk menyimpan indeks, tetapi tidak sengaja menemukan jawaban ini, saya berharap saya bisa upvote 1000 kali, terima kasih!
Evgeniy Kleban
1
Solusi hebat Terima kasih telah menghabiskan waktu berjam-jam untuk mengatasi masalah ini
Vision Mkhabela
Ini hanya mengembalikan nilai 0. Apakah saya melakukan sesuatu yang salah
N. Der
35

Membangun Jawaban Ole…

Beginilah cara saya menerapkan 4 metode untuk melacak halaman saat ini dan memperbarui indikator halaman ke indeks yang benar:

- (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
sumber
2
Saya pikir baris terakhir harus self.nextIndex = self.currentIndexdaripada self.nextIndex = 0untuk mengembalikan indeks dengan benar ketika transisi tidak selesai. Jika tidak, Anda berisiko berakhir dengan currentIndexnilai 0 saat berpindah halaman dengan cepat ke suatu tempat di tengah halaman Anda.
hverlind
1
Ini tidak sepenuhnya berhasil untuk saya. Terkadang, pageViewController: willTransitionToViewControllers tidak dipanggil dan oleh karena itu nextIndex tidak berubah, dan indeks saat ini salah.
Hayden Holligan
31

Solusi di bawah ini berhasil untuk saya.

Apple dapat menghindari banyak kerumitan dengan membuat paginasi tampilan gulir UIPageViewController asli lebih dapat dikonfigurasi. Saya harus menggunakan overlay UIView dan UIPageControl baru hanya karena pagination UIPageViewController asli tidak mendukung latar belakang transparan atau reposisi dalam bingkai tampilan.

- (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
sumber
1
dalam hal ini yang Anda maksud dengan indeks?
Yohan
Saya mendapatkan indeks (yaitu, bilangan bulat yang mewakili posisi pengontrol tampilan saat ini dalam larik self.pageViewController.viewControllers) dan kemudian menggunakannya untuk menyetel atribut currentPage dari self.pageControl (yang mengharapkan nilai integer) . Masuk akal?
sirvine
6
indeks adalah properti khusus di sini saya percaya
Adam Johns
Masalah dengan ini adalah bahwa jika Anda ingin mengubah halaman tanpa metode animasi tidak akan dipanggil
Silviu St
19

Cepat 4

Tidak ada kode yang tidak perlu. 3 cara melakukannya. Menggunakan metode 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
sumber
Terima kasih Tuhan! Saya tidak tahu tentang pageViewController.viewControllers. Bagaimana Anda tahu viewControllers?. Pertama yang dimaksud?
Script Kitty
Cukup sederhana sebenarnya, array viewControllers hanya berisi pengontrol tampilan yang saat ini disajikan.
Nikola Milicevic
2
bagaimana cara mengakses variabel indeks dari fungsi itu?
N. Der
11

Saya melacak indeks halaman dengan menggunakan fungsi kecil dan menentukan pageIndex sebagai NSInteger statis.

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

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

dan memanggil [self setPageIndex];di dalam fungsi yang ditentukan oleh Ole dan juga setelah mendeteksi perubahan orientasi.

Wahib Ul Haq
sumber
5

Saya pertama kali menggunakan solusi Corey tetapi tidak berfungsi di iOS5 kemudian akhirnya menggunakan,

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

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

Ini mencoba beralih melalui halaman yang berbeda dan berfungsi dengan baik untuk saat ini.

Basit Ali
sumber
3

Sayangnya tidak ada di atas yang berhasil untuk saya.

Saya memiliki dua pengontrol tampilan dan ketika saya sedikit (sekitar 20px) menggulir tampilan terakhir ke belakang, itu memicu delegasi:

pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:

dan mengatakan bahwa halaman saat ini (indeks) adalah 0yang salah.

Menggunakan delegate di dalam viewController anak seperti:

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

// and a property

@property (nonatomic) NSInteger index;

yang dipicu di dalam viewDidAppearseperti:

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

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

Bekerja untuk saya.

0yeoj
sumber
3

Ini bekerja untuk saya dengan andal

Saya memiliki UIPageController kustom. PageController.currentPage ini diperbarui dari UIViewController yang ditampilkan di 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
sumber
1

Saya telah menggunakan view.taguntuk sementara waktu sekarang, mencoba melacak halaman ini terlalu rumit.

Dalam kode ini indeks disimpan dalam tagproperti masing-masing viewdan digunakan untuk mengambil VC berikutnya atau sebelumnya. Menggunakan metode ini juga memungkinkan untuk membuat gulungan tak terbatas. Lihat komentar dalam kode untuk melihat solusi ini juga:

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
sumber
1

Terima kasih atas jawaban Anda, saya menghadapi masalah yang sama, harus menyimpan indeks. Saya sedikit mengubah kode saya, tempel di bawah ini:

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

Di bawah kode demo (di Swift 2) yang mendemonstrasikan bagaimana hal ini dilakukan dengan menerapkan tutorial penyapu gambar sederhana. Komentar di kode itu sendiri:

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

Saya memiliki array viewControllers, yang saya tampilkan di 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
}
}

Hal yang penting untuk dicatat di sini adalah bahwa setViewControllers metode UIPageViewController tidak memberikan delegasi callback. Callback delegasi hanya mewakili tindakan sentuhan pengguna di UIPageViewController .

jarora
sumber
0

Ini adalah solusi yang saya dapatkan:

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

Pemakaian:

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

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

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

Pastikan untuk menyetel judul awal

Peter Combee
sumber
0

Cara termudah untuk mendekati IMHO ini adalah dengan menggunakan PageControl untuk menyimpan hasil potensial dari transisi dan kemudian mengembalikannya jika transisi dibatalkan. Ini berarti bahwa kontrol halaman berubah segera setelah pengguna mulai menggesek, itu tidak masalah bagi saya. Ini mengharuskan Anda memiliki array UIViewControllers Anda sendiri (dalam contoh ini disebut 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
    }
}
swift taylor
sumber
0

Bagaimana kalau meminta viewControllerlangsung dari UIPageViewController(Swift 4 versi):

fileprivate weak var currentlyPresentedVC: UIViewController?

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

Atau, jika Anda hanya memerlukan pengontrol tampilan yang saat ini disajikan di beberapa titik waktu, cukup gunakan pageViewController.viewControllers?.firstsaat itu.

Milan Nosáľ
sumber
0

Dalam 5 cepat dan jawaban sirvine berikut

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
        }

    }

} 

Dalam hal ini saya tidak peduli kelas apa dari UIViewController yang disematkan

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

Ini akan mengembalikan indeks halaman saat ini. dan harus menggunakan kode ini di bawah fungsi delegasi UIPageViewController (didFinishAnimating).

Vinay Podili
sumber