UIPageViewController : 현재 보이는 뷰를 반환


89

안에 현재 페이지 /보기가 무엇인지 어떻게 알 수 UIPageViewController있습니까?

viewDidAppear내 자식 뷰 의 메서드를 재정 의하여 메서드에서 부모 뷰에 ID를 보냅니다 viewDidAppear.

그러나 문제는 이것입니다. 표시된 페이지의 ID로 해당 ID를 안정적으로 사용할 수 없습니다. 사용자가 페이지를 넘겼지만 중간 쯤에 넘기기를 중지하고 페이지를 되돌리기로 결정 viewDidAppear했다면 이미 호출되었을 것입니다. (보기는 말린 페이지 뒤에 표시됩니다).

현재보기가 사라지면 새 ID로만 전환해야 할 수도 있습니다. 하지만 현재 보이는 뷰를 반환하는 더 간단한 방법이 없는지 궁금합니다.


viewDidAppear:animated:대신 사용해 보셨습니까 ?
까지

오, 그래. 나는 그것을 사용했다. 내 실수를 바로 잡기 위해 질문을 편집했습니다.

질문을 편집 한 방식이 이해가되지 않습니다. viewWillAppear 또는 viewDidAppear에서 해당 ID를 보냅니다. 편집 내용을 다시 확인하십시오.
까지

죄송합니다. 질문을 잘못 수정했습니다. 나는 항상 viewDidAppear를 사용했습니다. 마지막 편집이 그것을 명확히하기를 바랍니다.

여기 얘들 아, 이것은 나를 위해 작동합니다 stackoverflow.com/a/36860663/4286947
theDC

답변:


103

현재 페이지를 수동으로 추적해야합니다. 델리게이트 메서드 pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:는 해당 변수를 업데이트 할시기를 알려줍니다. 메서드의 마지막 인수는 transitionCompleted:사용자가 페이지 넘기기 전환을 완료했는지 여부를 알려줍니다.


1
+1 정답-UIPageViewController로 작업하고 iOS5 만 지원할 기회가 있었으면합니다.
까지

감사합니다. 이것이 제가 찾던 깨끗한 솔루션입니다. 페이지의 대표자보다 낫습니다.

3
장치를 회전 할 때 현재 페이지를 어떻게 추적합니까?
Satyam

@till 당신은 단지 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에서 더 이상 올바른 뷰 컨트롤러를 얻지 못합니다. 그래서 항상 .NET Framework에 의존하는 대신 내 자신의 currentPage 속성을 유지하기 위해 고수했습니다 viewControllers.
Fábio Oliveira

재미있는, 나는이 특별한 경우에 작동하는 방법을 조금보고 그것으로 플레이를 해
에디 보르를

2
또한 신뢰할 수없는 것으로 나타났습니다. Apple은 각 페이지 회전에 대해 viewControllerBeforeViewController 또는 viewControllerAfterViewController를 호출하지만 UIPageViewController.viewControllers를 업데이트하지 않는 것 같습니다. 나는 그들이 이러한 유형의 일을 잘못 처리하기 위해 어떻게 계속 관리하는지 모르겠지만 그들은 그렇게합니다. 그것은 정말로 내 작업 부하를 높이고 내 코드의 명확성을 깨뜨립니다 (종종 DRY 및 기타 원칙 위반).
잭 모리스

3
@ZackMorris. 정말 대단합니다. 당신 말이 맞습니다. "애플 공포의 순간"입니다. 왜 그들이 오른쪽으로 한 페이지 이동, 현재 내가 어떤 페이지에 있는지 등과 같은 명백한 기능을 포함하지 않을까요? "현재 페이지를 가져올 수 없습니다 !!!"
Fattie 2014 년

1
self.viewControllers [0]이 잘 작동하는 것 같습니다. 하지만 시작하는 동안 setViewControllers를 한 번만 호출하고 나머지는 자동화에 맡겼습니다. (아이폰 OS 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;")로 설정해야합니다. 그렇지 않으면 메서드가 호출되지 않습니다. 이것은 나를 조금 당황하게했다.
James Toomey 2014-06-24

1
@VictorM이 솔루션은 나를 위해 작동하지 않습니다. 이미지가 다른 pageViewController가 있습니다. 스 와이프 할 때마다 태그 0을 계속 반환합니다. 왜 이런 일이 발생하는지 아십니까? 미리 감사드립니다
theDC

1
@VictorM 나는 색인을 저장하려고 며칠을 보냈지 만 우연히이 답변을 찾았습니다 .1000 번 찬성 할 수 있기를 바랍니다. 감사합니다!
Evgeniy Kleban

1
훌륭한 솔루션 덕분에이 주변려고 시간을 보냈다
비전 Mkhabela

0의 값만 반환합니다. 내가 뭔가 잘못하고
N. Der

35

Ole의 답변을 바탕으로…

이것이 현재 페이지를 추적하고 페이지 표시기를 올바른 색인으로 업데이트하는 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 2014

1
이것은 나를 위해 완전히 작동하지 않습니다. 때로는 pageViewController : willTransitionToViewControllers가 호출되지 않아 nextIndex가 변경되지 않고 현재 색인이 잘못되었습니다.
Hayden Holligan 2015

31

아래 솔루션이 저에게 효과적이었습니다.

Apple은 네이티브 UIPageViewController 스크롤 뷰 페이지 매김을보다 구성 가능하게 만들어 많은 번거 로움을 피할 수 있습니다. 네이티브 UIPageViewController 페이지 매김이 투명한 배경을 지원하지 않거나 뷰 프레임 내에서 재배치되지 않기 때문에 새 UIView 및 UIPageControl을 오버레이해야했습니다.

- (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
이것에서 색인이란 무엇을 의미합니까?
Yohan

인덱스 (즉, self.pageViewController.viewControllers 배열에서 현재 뷰 컨트롤러의 위치를 ​​나타내는 정수)를 얻은 다음이를 사용하여 self.pageControl의 currentPage 속성 (정수 값을 예상 함)을 설정합니다. . 말이 되나?
sirvine 2014

6
지수는 내가 믿는 여기에 사용자 정의 속성입니다
아담 존스

이것에 문제는 애니메이션 방법없이 페이지를 변경하려면 호출되지 것입니다
실비 세인트

19

스위프트 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 배열에는 현재 제시된 뷰 컨트롤러 만 포함됩니다.
Nikola Milicevic

2
해당 함수에서 인덱스 변수에 어떻게 액세스합니까?
N. Der

11

작은 함수를 사용하고 pageIndex를 정적 NSInteger로 지정하여 페이지 인덱스를 추적하고 있습니다.

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

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

[self setPageIndex];Ole이 지정한 함수 내부 를 호출 하고 방향 변경을 감지 한 후 호출 합니다.


5

처음에는 Corey의 솔루션을 사용했지만 iOS5에서 작동하지 않고 결국 사용하게되었습니다.

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

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

다른 페이지로 전환을 시도했으며 현재는 잘 작동합니다.


3

불행히도 위의 아무것도 나를 위해 작동하지 않습니다.

두 개의 뷰 컨트롤러가 있고 약간 (약 20px) 마지막 뷰를 뒤로 스크롤하면 델리게이트가 트리거됩니다.

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

나를 위해 일했습니다.


3

이것은 나를 위해 안정적으로 작동합니다.

사용자 지정 UIPageController가 있습니다. 이 pageController.currentPage는 viewWillAppear에 표시된 UIViewController에서 업데이트됩니다.

   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

나는 한동안 사용 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

답변 주셔서 감사합니다. 비슷한 문제에 직면하여 색인을 저장해야했습니다. 코드를 약간 수정하고 아래에 붙여 넣습니다.

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

}

0

UIPageViewController에 표시하는 viewControllers 배열이 있습니다 .

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 에서 사용자 터치 액션만을 나타냅니다 .


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을 사용하여 전환의 잠재적 결과를 저장 한 다음 전환이 취소 된 경우 되 돌리는 것입니다. 이것은 사용자가 스 와이프를 시작하자마자 페이지 컨트롤이 변경됨을 의미합니다. 이를 위해서는 UIViewController의 고유 한 배열이 있어야합니다 (이 예제에서는 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

(Swift 4 버전) viewController에서 직접 요청하는 방법 UIPageViewController:

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)의 위임 함수에서이 코드를 사용해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.