陈述:
似乎 Apple 已经发现开发人员在非常不同的应用程序中使用 UIPageViewController,这些应用程序超出了 Apple 最初基于其设计选择的最初预期的应用程序。而不是以手势驱动的线性方式使用它,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 的角度来看 Apple 是否非常喜欢看到 PVC 以这种方式使用,但是 - 它不会破坏向后兼容性,这是一个简单的修复,所以 - 他们最终做到了。实际上,这只是对两个 DataSource 方法之一的再调用一次,这在页面(ViewController)已经被兑现以供以后使用的线性环境中是绝对不必要的。
然而,即使这种增强对于某些用例可能非常方便,类的初始行为也不能被视为错误。许多开发人员这样做的事实——也在 SO 上的其他帖子中指责 UIPageViewController 行为不端——而是强调了对其设计、目的和功能的广泛传播的误解。
在没有试图冒犯这个伟大设施中的任何开发人员的情况下,我仍然决定不删除我最初的“调查”,该“调查”清楚地向 OP 解释了 PVC 的机制以及为什么他的假设是错误的,即他必须在这里处理一个错误.
这对于在 UIPageViewController 的实现中遇到一些复杂问题的任何其他开发人员也可能有用!
原始答案:
在一遍又一遍地阅读所有答案之后 - 包括接受的答案 - 还有一件事要说......
的设计UIPageViewController
绝对是完美无瑕的,你提交的所有黑客为了规避所谓的错误只不过是对你自己错误假设的补救措施,因为你一开始就搞砸了!!!
根本没有错误!你只是在与框架作斗争。我会解释为什么!
关于页码和索引的讨论太多了!这些是控制器一无所知的概念!它唯一知道的是 - 它正在显示一些内容(顺便说一句。由您作为dataViewController提供)并且它可以执行诸如右/左动画之类的操作以模仿翻页。
CURL
或者SCROLL
……!!!
在pageViewController的世界中只存在一个 current SPACE
(让我们这样称呼它以避免与页面和索引混淆)。
当您最初设置pageViewController时,它只关心这一点SPACE
。只有当您开始平移它的视图时,它才会开始询问DataSource
它最终应该显示什么,以防发生左/右翻转。当您开始向左平移时,PVC 会先询问BEFORE-SPACE
,然后
询问AFTER-SPACE
,如果您从右侧开始,它会反其道而行之。
在完成动画之后(SPACE
PVC 的视图显示一个新的),PVC 认为这SPACE
是它的新宇宙中心,当它在它的时候,它会询问DataSource
它仍然不知道的那个。如果完成向右转弯,它想知道新AFTER
空间,如果完成向左转弯,它会要求新BEFORE
空间。
旧BEFORE
空间(从动画之前开始)在完成向右转的情况下完全过时,并尽快被释放。旧center
的现在是新BEFORE
的,以前AFTER
的就是新的center
。一切都只是向右移动了一步。
所以 - 没有谈论“哪个页面”或“任何索引” - 只是简单地 - 有一个BEFORE
或一个AFTER
空格。如果您将 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
动画的方向(例如) - 如果有一个意图 - 换句话说只是意味着 -> 去
BEFORE
或AFTER
......
再次 - 没有提及索引,页码等......!
这只是一种以编程方式实现相同手势的方式!并且 PVC 在首先向右移动后再次向左移动时再次显示旧内容是正确的。请记住——它只是以结构化的方式显示(你提供的)内容——这是'single page turn'
设计使然!!!
这就是翻页的概念——或者 BOOK,如果你更喜欢这个词的话!
仅仅因为您在第 1 页之后提交第 8 页来搞砸它并不意味着 PVC 完全关心您对一本书应该如何工作的扭曲看法。你的应用程序的用户也不是。向右和向左翻转肯定会导致到达原始页面 - 如果使用动画完成。您可以通过为灾难找到解决方案来纠正错误。不要把它归咎于UIPageViewController
. 它完美地完成了它的工作!
问问自己——你会用PAGE-CURL
动画做同样的事情吗?不 ?好吧,你也不应该用SCROLL
动画!动画翻页是翻页,只是翻页!无论哪种模式!如果您决定撕掉书的第 2 页到第 7 页,那就太好了!但是不要指望UIPageViewController
在返回最近的页面时发明一个不存在的第 7 页,除非你告诉它事情已经改变了......
如果你真的想实现一个不协调的跳转到其他地方,那么 - 没有动画就可以了!在大多数情况下,这不会很优雅,但是 - 有可能...... -
而且 PVC 甚至可以很好地配合!当跳转到SPACE
没有动画的新内容时,它会询问您是否需要进一步了解 -BEFORE
和AFTER
控制器。所以你的应用程序逻辑可以跟上 PVC ......
但是对于您始终在传达的动画 - 移动到上一个/下一个空间(BEFORE -
AFTER
)。所以从逻辑上讲,PVC 根本不需要在动画翻页时再次询问它已经知道的空间!!!
如果您想在从第 1 页动画到右侧后向左翻转时看到第 7 页 - 好吧,我会说 - 这绝对是您自己的问题!
并且以防万一您正在寻找比已接受答案中的“完成块”破解更好的解决方案(因为您正在事先为一些可能甚至可能不会在以后使用的东西提前工作)使用手势识别器代表:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
如果您真的打算向左返回第 7 页,则在此处设置您的 PVC 的 DataViewController(没有动画),并且DataSource
将被要求BEFORE
并且AFTER
您可以提交您喜欢的任何页面!当你从第 1 页到第 8 页进行不受控制的跳跃时,你应该隐藏一个标志或 ivar,这应该没问题......
当人们继续抱怨 PVC 中的一个错误时——在应该只翻 1 翻的情况下翻了 2 页——将他们指向这篇文章。
同样的问题 - 在转换手势中触发未动画的setViewControllers:方法将导致完全相同的破坏。您认为您设置了新中心 - 要求 DataSource 提供新的BEFORE - AFTER
dataController - 您重置了索引计数...... - 好吧,这似乎没问题......
但是 - 在所有这些业务之后,PVC 结束了它的转换/动画并想知道下一个(仍然未知)dataViewController(BEFORE
或AFTER
)并且还触发DataSource
. 这是完全合理的!它需要知道它在它的小BEFORE - CENTER - AFTER
世界中的位置,并为下一回合做好准备。
但是您的程序逻辑在其逻辑中添加了另一个 index++ 计数,并且突然翻了 2 页!这与您认为自己所处的位置不同。
你必须考虑到这一点!不是UIPageViewController
!!!
这正是 DataSourceProtocol 只有两种方法的重点!它希望尽可能通用——给你空间和自由来定义你自己的逻辑,而不是被别人的特殊想法和用例所束缚!逻辑完全取决于你。只是因为你找到了类似的功能
- (DataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard position:(GSPositionOfDataViewController)position;
- (NSUInteger)indexOfViewController:(DataViewController *)viewController;
在云中的所有复制/粘贴示例应用程序中,并不一定意味着您必须吃那些预先煮好的食物!以您喜欢的方式扩展它们!看看上面 - 在我的签名中你会发现一个'position:'
论点!我稍后将其扩展为知道完成的翻页是右转还是左转。因为不幸的是,代表只是告诉您您的回合是否完成!它不会告诉你方向!但这有时对索引计数很重要,具体取决于您的应用程序的需要......
发疯——它们是你的……
快乐编码!