2013-02-26 92 views
6

我看了很多很多地方,还没有找到一些很好的示例代码,显示如何在UIPageViewController中预加载“下一页”页面。 SO上有几个答案,详细介绍了一些理论方法(见this question),但还没有人发布一个工作示例。预加载UIPageViewController中的下一页

在我的应用程序的工作流程中,我显示每个屏幕1页,并且我希望预加载“下一个”屏幕,因为实际上,滑动到下一页可能非常缓慢,有时需要2次滑动(如果你刷得太快),以便下一页被渲染和显示。这提供了糟糕的用户体验。我并不在乎预先加载“之前”或其他任何屏幕,因为典型的工作流程是用户在屏幕上停留一段时间,然后再转到下一个屏幕(向右)。我正在使用幻灯片动画(不是蜷缩起来)。我以编程方式创建所有视图,完全不使用IB。

我试图将一些UIViewControllers存储在一个NSMutableArray中,并从那里加载控制器,但它很难做到正确工作,似乎并没有加快速度。必须有一个很好的方法来做到这一点。

任何帮助,非常感谢。

+1

您是否找到了解决方案?我有同样的问题,滑到下一个视图控制器时会显着滞后。 – mattsson 2014-02-20 09:23:20

+0

排序,但答案是非常具体的我的实施。正如我在发布这个问题后与UIPageViewController合作过很多,我发现这是一个非常棘手的问题。基本上,我的问题更多的是与查询数据库查询正确的数据有关,这会减慢每个页面的速度。我能够通过预先计算数据库中的数据,并使用自动布局绘制视图而不是混乱框架来优化页面轮换 - 这对我们有很大的帮助。其次我有很多的图像显示,所以我直接在“主”视图控制器(滑动的父)将它们存储在一个NSMutableArray中。 – DiscDev 2014-02-20 15:41:46

+0

我的“解决方案”最终成为......不断等待苹果公司推出更快的手机......哈哈哈。在iPhone 6/6s上,不再有延迟。我优化了一些数据库抓取代码,当页面控制器第一次创建时会发生一次并且帮助了很多,但主要的速度改进来自更快的处理器和更多的RAM,并且逐步取消对iPhone 4/4s的支持=) – DiscDev 2015-10-12 19:05:46

回答

0

您应该使用例如Instruments的Time Profiler来调试您的代码。 这样做,你会发现哪个对象具有最高的运行时间。 也许与UIPageViewController无关,但与页面内的视图无关。

2

我已经解决了我的情况有点破解。对于每个ContentView,我有一个UIScrollView内的UIImageView用于缩放。我的问题是,在启动应用程序时,如果用户在刷卡之前放大,在放大时进入下一页将无法正常工作。我使用下面的代码(Swift 1.2)来解决这个问题。正如我所说的那样,这虽然有些破绽。

var layoutsubs = false 

override func viewDidLoad() { 
    super.viewDidLoad() 
    //Other code for implementing pageViewController omitted 

    //add pageViewController to main view 
    self.addChildViewController(pageViewController) 
    self.view.addSubview(pageViewController.view) 
    pageViewController.didMoveToParentViewController(self) 

    //Load to the viewController after the starting VC, then go back to the starting VC 
    var viewControllers = [afterVC] 
    pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil) 
    viewControllers = [startingVC] 
    pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Reverse, animated: true, completion: nil) 
} 

override func viewWillLayoutSubviews() { 
    //Load the viewController before the starting VC then go back to the starting VC 
    //viewWillLayoutSubviews() is called multiple times, so do this only once 
    if !layoutsubs { 
     let startingVC = self.viewControllerAtIndex(imageIndex) as ContentViewController 
     let beforeVC = pageViewController(pageViewController, viewControllerBeforeViewController: startingVC) as! ContentViewController 

     var viewControllers = [beforeVC] 
     pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Reverse, animated: true, completion: nil) 
     viewControllers = [startingVC] 
     pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil) 
     layoutsubs = true 
    } 
} 

本质上,我加载视图控制器之前和之后的起始视图控制器。我通过将每个设置为VC来通过setViewControllers(_:direction:animated:completion:)see ref)来查看,然后返回到起始视图控制器。为什么这是两个不同的功能?那么,如果你把它放在一个,那么只有启动VC旁边的两个视图控制器中的一个会加载。这对某些情况可能是需要的,但我需要所有三个VC(加载之前,开始和之后)。

我不确定如果UIPageViewController已经被加载,这个方法可以工作多好。例如,如果您需要将页面2加载离开正在查看的页面,则需要几次滑动。如果你把它放在willTransitionToViewControllers()中,它可能会跳过。

+0

如果你没有固定数量的风险投资,这是如何工作的?有没有一种方法可以一次预加载所有的数据,所以没有问题?谢谢! – Jacob 2015-12-17 06:55:57

+0

@Jacob:如果您没有固定数量的VC,那么您首先必须检查所选VC之前和之后是否存在VC。如果后面只有一个VC,则只能使用viewDidLoad()中的代码,并且不会使用viewWillLayoutSubviews()。如果在它之前只有一个VC,你将使用'viewWillLayoutSubviews()'中的代码,'viewWillLoad'中的所有内容都将从'// Load to viewController'开始。在这种情况下,您可以在'viewDidLoad()'中转到前一个VC。我不确定如何预装所有风险投资,对不起。 – 2016-01-04 08:22:10

+0

你好,你可以提供初始化pageViewController完整的代码来完成它 – 2016-03-10 07:39:59