UIPageViewController导航到错误的页面,滚动式的转型(UIPageViewCont

2019-06-18 13:43发布

我UIPageViewController在的iOS 5,工作正常,但在iOS 6中走过来的,我想用新的滚动过渡方式(UIPageViewControllerTransitionStyleScroll),而不是页面卷曲风格。 这引起了我的UIPageViewController打破。

它工作正常,除了右后我打过电话setViewControllers:direction:animated:completion: 。 在此之后,下一次用户手动滚动一页,我们得到了错误的页面。 什么是错在这里?

Answer 1:

我的这个错误的解决方法是创建一个块结束时,这是设置在同一视图 - 控制,但没有动画

__weak YourSelfClass *blocksafeSelf = self;     
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished){
            if(finished)
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [blocksafeSelf.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];// bug fix for uipageview controller
                });
            }
        }];


Answer 2:

这实际上是在UIPageViewController的错误。 它只用滚动式的(UIPageViewControllerTransitionStyleScroll),只有调用后发生setViewControllers:direction:animated:completion: 与动画:是 。 因此,有两种解决方法:

  1. 不要使用UIPageViewControllerTransitionStyleScroll。

  2. 或者,如果你调用setViewControllers:direction:animated:completion: ,只能使用animated:NO

看到错误清楚,呼叫setViewControllers:direction:animated:completion:然后,在接口(如用户),导航手动左(后)到前一页。 您将浏览返回错误页面:没有前面的页面可言,但你在页面setViewControllers:direction:animated:completion:被调用。

究其原因,错误似乎是,使用滚动式的时候,UIPageViewController做一些内部的缓存。 因此,呼叫后setViewControllers:direction:animated:completion: ,它不能清除其内部缓存。 它认为它知道前面的页面是什么。 因此,当用户导航到向左前一页,UIPageViewController 失败调用则dataSource方法pageViewController:viewControllerBeforeViewController:或与错误的当前视图控制器调用它。

我已经发布的影片清楚地说明看到的错误:

http://www.apeth.com/PageViewControllerBug.mov

编辑这个bug可能会被固定在IOS 8。

编辑有关此漏洞另一个有趣的解决办法,看到这样的回答: https://stackoverflow.com/a/21624169/341994



Answer 3:

这里是一个“粗”要点我放在一起。 它包含一个UIPageViewController的替代方案,从患有老年痴呆症(即:它没有苹果实现的内部缓存)。

这个类是不完整的,但它在我的情况(即:水平滚动)的作品。



Answer 4:

如的iOS 12在原来的问题中描述的问题似乎几乎固定。 我来到这个问题,因为我在我的特别设置,其中它还是发生了经历过,所以这个词“差不多”在这里。

我遇到此问题的设置为:1)应用程序是通过基于链接的应用程序必须切换到一个特定的标签并没有打开给定项目通过描述推3)问题上的深层链接2)打开只发生在目标标签之前未被用户选择的(使得UIPageViewController应该以动画到该选项卡),并且仅当setViewControllers:direction:animated:completion:已经animated = true 4)推回到回包含UIPageViewController视图控制器之后,后者被认为是一个很大的混乱 - 这是呈现完全错误的视图控制器,即使调试表明一切的逻辑电平罚款

我认为,问题的根源是,我是推视图控制器后很快setViewControllers:direction:animated:completion:叫,使UIPageViewController机会都没有完成的东西(也许动画,或高速缓存,或别的东西)。

只要通过延迟我的纲领性导航UI给人UIPageViewController一些空闲时间

 DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) { ... } 

固定我的问题。 而这也让被链接的项目更加用户友好的编程开幕视觉。

希望这有助于有人在类似的情况。



Answer 5:

此错误仍然存​​在iOS9。 我使用的是乔治Tsifrikas上面贴了相同的解决方法,但斯威夫特的版本:

    pageViewController.setViewControllers([page], direction: direction, animated: true) { done in
        if done {
            dispatch_async(dispatch_get_main_queue()) {
                self.pageViewController.setViewControllers([page], direction: direction, animated: false, completion: {done in })
            }
        }
    }


Answer 6:

由于pageviewVC调用多childVC时刷卡吧。 但是,我们只需要最后一页是可见的。

就我而言,我需要改变指数分段控制时变化浏览量。

希望这帮助别人:)

extension ViewController: UIPageViewControllerDelegate {

    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        guard let pageView = pageViewController.viewControllers?.first as? ChildViewController else { return }
        segmentedControl.set(pageView.index)
    }
}


Answer 7:

声明:

看来,苹果已经发现,开发商都在走的方式超越了原本有意的苹果公司基于在首位他们的设计选择非常不同的应用程序中使用UIPageViewController。 而不是在一个手势驱动线性方式使用它PVC通常用于结构化环境中以编程跳转到随机的位置。 因此,他们已经提高了他们执行UIPageViewController和类是现在呼吁双方的DataSource回调

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController

与UIPageViewController设置新contentViewController后

[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];

即使网页动画转,而建议在如页面层次结构就像一本书或PDF文件使用连续的页面的线性进步。 虽然 - 我怀疑苹果从HIG的角度来看是非常喜欢看PVC使用这种方式,但是 - 它不会破坏向后兼容性,这是一个简单的办法,所以 - 他们最终做到了。 其实这是两个数据源的方法是在页面(ViewControllers)已经兑现以备以后使用的线性环境完全没有必要一只是多了一个电话。

然而,即使这可能会增强进来对某些使用情况非常方便类的初始行为是不被认为是一个错误。 还上,这样指责不当行为的UIPageViewController其他职位 - - ,很多开发商做的事实,而强调它的设计,目的和功能的广泛流传的误解。

如果没有试图在这个伟大的设施在这里得罪我的任何开发伙伴我仍然决定不删除我的最初的“专题论文”,清楚地解释到OP PVC的力学和为什么他的假设是错误的,他就到这里处理的错误。

这也可能是使用的任何其他研究员也开发谁在UIPageViewController执行一些复杂的斗争!


原来的答案:

在已经一遍又一遍地阅读所有的答案 - 包括接受一个 - 有只是一两件事可说的......

设计UIPageViewController是绝对完美无瑕 ,你为了规避被指控的错误是什么,但对于自己的错误的假设补救办法,因为你在第一个地方出了差错它提交所有的黑客!

没有BUG了! 你只是战斗的框架。 我会解释为什么!


有这么多谈页码和指数! 这些概念控制器知道什么 ! 它知道的唯一事情就是-它显示一些内容(顺便说一句你所提供的dataViewController),它可以这样做左/右动画以模拟翻页。 CURLSCROLL ... !!!

pageViewController的世界只存在一个电流SPACE (姑且称之为正是以这种方式来避免与网页和指数的混乱)。

当您最初设置pageViewController它只是心中对此非常SPACE 。 只有当你开始平移视图它开始要求它的DataSource是什么,最终应该在情况下,左/右翻转应该发生的显示。 当你开始平移,左侧是PVC首先要求对BEFORE-SPACE然后为AFTER-SPACE ,如果你开始它用另一种方式圆的权利。

已完成的动画(一个新的后SPACE是由PVC的视图中显示)的PVC认为这个SPACE作为其新宇宙的中心,而这是它,它要求DataSource对一个它仍然不知道任何有关。 在完成转就是了了解新的权利的情况下, AFTER空间,并在完成转向时,要求提供新左的情况下, BEFORE的空间。

BEFORE空间(从动画前)在完成右转完全过时的情况下,并得到尽快释放。 老center是现在新BEFORE和前AFTER是新的center 。 一切都只是转移一步的权利。

所以-没有“ 哪个页面 ”或通话“ 不管指数 ” -只是简单-有一个BEFOREAFTER空间。 如果返回NIL到的一个DataSource的回调PVC就假定它是你的一个极端的range of SPACES 。 如果返回NIL既回调它假定它显示了one and only SPACE存在,永远不会再调用过一个DataSource回调了! 其中的逻辑是你了! 你定义在你的代码页和指数! 不是PVC!


对于类的用户存在与PVC相互作用的两种手段。

  • A pan-gesture that indicates whether a turn to the BEFORE/AFTER space is desired
  • A method - namely setViewControllers:direction:animated:completion:

这种方法确实比移动手势是做完全一样的。 您指示方向(例如UIPageViewControllerNavigationDirectionBackward/Forward )的动画-如果有一个预期-这,换句话说只是意味着- >去BEFOREAFTER ...

再次 - 不提指标,页面数等...!

这仅仅是达到同样的手势会的编程方式! 而PVC是通过再次显示搬回到左侧时,在第一时间已经向右移动后的旧内容的权利这样做。 请记住-它只是显示的内容(您提供)以结构化方式-这是一个'single page turn'设计!

这是翻页的概念 - 或书,如果你喜欢这个词更好!

仅仅因为你偷懒它通过PAGE后提交第8页1并不意味着PVC关心的所有关于你的书应该如何工作扭曲的看法。 和你的应用程序没有的用户。 翻转到右侧,回左侧绝对应该引起达到原来的页面 - 如果与动画来完成。 它是由你通过查找为灾区解决纠正混日子。 不要责怪UIPageViewController 。 这是完全做它的工作!

问问你自己-你会做同样的事情用PAGE-CURL动画? NO? 好了,你们也不应以SCROLL动画! 动画翻页效果翻页,只翻页! 在这两种模式! 如果你决定要撕下PAGE 2你的书的第7页这是完全正常的! 但就是不指望UIPageViewController发明一种不存在的页面7义无反顾近期页,除非你告诉它当一切都变了......


如果你真的想实现的不协调跳转到其他地方,以及 - 做没有动画! 在大多数情况下,这将不会是很优雅,但 - 这是可能的... -

而PVC甚至起到很好的一起! 当跳跃到一个新的SPACE ,而不动画会进一步问你下来两个路- BEFOREAFTER控制器。 所以,你的应用程序逻辑可以跟上PVC ...

但随着动画你总是输送-移动到上一个/下一个空格( BEFORE - AFTER )。 因此,逻辑上没有必要在所有的PVC再次询问关于动画翻页的时候,它已经知道的空间!

如果你想看到PAGE 7从第1页已经动画向右翻转后回到左边时 - 好吧,我会说 - 这绝对你自己的问题!


以防万一你正在寻找比“完成块”从公认的答案破解(因为有了它,你正在做的工作,事先的东西,有可能会甚至无法继续使用的道路)使用手势识别一个更好的解决方案代表:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

在此处设置PVC的DataViewController(不包括动画),如果你真的打算回去留给PAGE 7和DataSource将被要求BEFOREAFTER ,你可以提交你喜欢的任何页面! 与从第1页做你的不受控制的跳的时候到8这应该是没有问题的,你应该已经卷走标志或伊娃...


而当人们不断抱怨在PVC中的错误 - 这样做时,它应该只能做1转2翻页 - 它们指向这篇文章。

同样的问题-触发的未动画setViewControllers:所述过渡手势内方法将导致完全一样的严重破坏。 你以为你设置新的中心-数据源被要求为新的BEFORE - AFTER DataController类-您重置索引计数... -嗯,这看起来不错...

但是-所有的业务后,PVC结束其过渡/动画,想了解下一个(还是未知数吧)dataViewController( BEFOREAFTER ),并触发DataSource 。 这是完全有道理的! 它需要知道在小BEFORE - CENTER - AFTER世界上是并为下一回合制得。

但是,你的程序逻辑又增加了指数++计数其逻辑和突然接到2页开启! 这就是从那里,你以为你是一个关。

必须考虑的! 不UIPageViewController


这正是该DataSourceProtocol点只有有两种方法! 它希望尽可能通用的 - 让你的空间和自由定义自己的逻辑,而不是被卡住别人的特殊思想和用例! 其中的逻辑是完全取决于你。 仅仅因为你发现像功能

- (DataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard position:(GSPositionOfDataViewController)position;
- (NSUInteger)indexOfViewController:(DataViewController *)viewController;

在所有的复制/云粘贴示例应用程序并不一定意味着你必须吃,库克预食物! 扩展他们你喜欢的任何方式! 只要看看上面-我的签名,你会发现一个'position:'说法! 我扩展了该知道以后是否完成翻页是一种权利或左转。 由于委托不幸只是告诉你是否轮到你完成与否! 它不会告诉你的方向! 但是,这有时事项的指数计数,这取决于你的应用程序的需要...

发疯 - 他们都是你的......

编码愉快!



文章来源: UIPageViewController navigates to wrong page with Scroll transition style