Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to make UIPageViewController reuse controller like tableview reuse cell?

I need a way to make UIPageViewController reuse controllers to save memory, because I have a huge number of pages to show! I did the basic implementation of the UIPageViewController but couldn't manage to make controller reusable, please advice!

like image 673
M.Alatrash Avatar asked Jul 02 '15 10:07

M.Alatrash


2 Answers

To solve this problem in my current project, I cache all view controllers that are created as pages for the UIPageViewController in a Set. Whenever the UIPageViewController requests a new view controller from its data source, I filter out an unused from that cache by checking the parentViewController property; if no unused view controller is available, a new one is created.

My setup of the UIPageViewController and the cache looks similar to this:

class MyPageViewController: UIPageViewController {
    private var reusableViewControllers = Set<MyViewController>()
    init() {
      super.init(/* ... */)
      self.dataSource = self

      let initialViewController = self.unusedViewController()

      // Configure the initial view controller
      // ...

      self.setViewControllers([ initialViewController ], 
                              direction: .Forward, 
                              animated: false, 
                              completion: nil)
    }

  // This function returns an unused view controller from the cache
  // or creates and returns a new one
  private func unusedViewController() -> MyViewController {
    let unusedViewControllers = reusableViewControllers.filter { $0.parentViewController == nil }
    if let someUnusedViewController = unusedViewControllers.last {
        return someUnusedViewController
    } else {
        let newViewController = MyViewController()
        reusableViewControllers.insert(newViewController)
        return newViewController
    } 
  }
}

The data source uses the same function to obtain an unused view controller:

extension MyPageViewController: UIPageViewControllerDataSource {
  func pageViewController(pageViewController: UIPageViewController,
                          viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        let nextViewController = unusedViewController()

        // Configure the next view controller for display
        // ...

        return nextViewController
    }
}
like image 59
Theo Avatar answered Oct 21 '22 06:10

Theo


You could use ACReuseQueue to achieve what you want. It provides a queue for reusing your view controllers. You can use the UIPageViewController data source methods to dequeue a VC from the reuse queue. The tricky part is to know when to put them back in the reuse queue. UIPageViewController does not provide any method to know when this happens, but there is a way. UIPageViewController is a container VC that adds and removes its child view controllers using the VC containment APIs. Your VC will receive didMoveToParentViewController: with nil as the argument if it is being removed from the UIPageViewController. Use this method to add yourself back to the queue.

like image 27
Miguel Cabeça Avatar answered Oct 21 '22 07:10

Miguel Cabeça