UIPageViewController:返回当前可见视图

Jan*_*Jan 88 iphone ios uipageviewcontroller

你怎么知道里面显示的当前页面/视图是UIPageViewController什么?

我已经覆盖了viewDidAppear我的子视图的方法,因此他们在viewDidAppear方法中向父视图发送了一个id .

但问题是:我无法可靠地将该id用作显示页面的id.因为如果用户转动页面但中途决定停止转动并将页面放回,viewDidAppear则已经被调用.(视图在卷曲页面后面可见).

也许我应该只在当前视图消失的情况下切换到新的id.但我想知道是否有更简单的方法来返回当前可见的视图?

Ole*_*ann 101

您应该手动跟踪当前页面.委托方法pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:将告诉您何时更新该变量.该方法的最后一个参数transitionCompleted:可以告诉您用户是否完成了翻页过渡.

  • 如何判断是增加还是减少当前页码? (78认同)
  • 旋转设备时,如何跟踪当前页面? (3认同)

Edd*_*rja 58

从iOS 6开始,我发现viewControllersUIPageViewController 的属性不断更新,因此它将始终保存一个代表当前页面的视图控制器,而不是其他内容.因此,您可以通过调用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;
    }
Run Code Online (Sandbox Code Playgroud)

请注意这是不可靠的评论.

  • 我发现它不可靠.我找不到问题的根源.当动画结束时,我访问`viewControllers`属性并获得正确的视图控制器,但是当我旋转时,在方法`spineLocationForInterfaceOrientation`上,我不再获得正确的视图控制器.所以我坚持维护自己的currentPage属性,而不是总是依赖于`viewControllers`. (2认同)
  • 我也发现它不可靠.似乎Apple只为每个页面转动调用viewControllerBeforeViewController或viewControllerAfterViewController,但不更新UIPageViewController.viewControllers.我不知道他们如何继续设法让这些类型的东西出错,但他们确实如此.它确实增加了我的工作量,并且破坏了我的代码的清晰度(经常违反DRY和其他原则). (2认同)
  • @ZackMorris.这绝对令人难以置信,你是对的.这是一个"苹果恐怖时刻".为什么哦,他们为什么不包括明显的功能,如向右移动一个,我当前在哪个页面等等.这是非常不可思议的,你不能"得到你所在的页面!!!" (2认同)

Vic*_*tor 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在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
}
Run Code Online (Sandbox Code Playgroud)

示例: gist

  • 好的解决方案 (5认同)
  • 这似乎是最直接的,对我来说效果很好.我在添加视图控制器时设置标签(例如,HelpPage1ViewController*page1 = [self.storyboard instantiateViewControllerWithIdentifier:@"page1"]; page1.view.tag = 0;).然后,您可以为主视图控制器设置currentPage属性,以跟踪您的位置.确保添加两个协议("<UIPageViewControllerDataSource,UIPageViewControllerDelegate>"),而不仅仅是数据源,并将委托设置为self("self.pageViewController.delegate = self;"),否则将不会调用该方法.这让我感到困惑. (3认同)

Cor*_*oyd 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;

}
Run Code Online (Sandbox Code Playgroud)

  • 我认为最后一行应该是`self.nextIndex = self.currentIndex`而不是`self.nextIndex = 0`,以便在转换未完成时正确恢复索引.否则,当你在页面中间的某个地方快速来回切换时,你可能会以'currentIndex`值为0结束. (2认同)

sir*_*ine 31

下面的解决方案对我有用.

通过使本机UIPageViewController滚动视图分页更加可配置,Apple可以避免许多麻烦.我不得不求助于覆盖新的UIView和UIPageControl只是因为本机UIPageViewController分页不支持透明背景或在视图框架内重新定位.

- (void)pageViewController:(UIPageViewController *)pvc didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
  if (!completed)
  {
    return;
  }
  NSUInteger currentIndex = [[self.pageViewController.viewControllers lastObject] index];
  self.pageControl.currentPage = currentIndex;
}
Run Code Online (Sandbox Code Playgroud)

  • 我相信index是一个自定义属性 (6认同)

Nik*_*vic 18

斯威夫特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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如何从该函数中访问索引变量? (3认同)

Wah*_*Haq 11

我通过使用一个小函数并将pageIndex指定为静态NSInteger来跟踪页面索引.

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

    pageIndex = [self.modelController indexOfViewController:theCurrentViewController];
}
Run Code Online (Sandbox Code Playgroud)

并且[self setPageIndex];在Ole指定的函数内部调用,并且在检测到方向的变化之后.


Bas*_*Ali 5

我第一次使用Corey的解决方案,但它不能在iOS5上工作,然后最终使用,

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

    if(completed) {
        _currentViewController = [pageViewController.viewControllers lastObject];
    }
}
Run Code Online (Sandbox Code Playgroud)

它尝试切换不同的页面,现在效果很好.