如何使 UIPageViewController 像 tableview 重用单元一样重用控制器?
Posted
技术标签:
【中文标题】如何使 UIPageViewController 像 tableview 重用单元一样重用控制器?【英文标题】:how to make UIPageViewController reuse controller like tableview reuse cell? 【发布时间】:2015-07-02 10:41:21 【问题描述】:我需要一种方法让 UIPageViewController 重用控制器以节省内存,因为我有大量的页面要显示! 我做了 UIPageViewController 的基本实现,但无法使控制器可重用,请指教!
【问题讨论】:
【参考方案1】:为了在我当前的项目中解决这个问题,我将所有为UIPageViewController
创建为页面的视图控制器缓存在Set
中。每当UIPageViewController
从其数据源请求新的视图控制器时,我通过检查parentViewController
属性从该缓存中过滤出未使用的视图控制器;如果没有可用的未使用的视图控制器,则创建一个新的。
我的UIPageViewController
和缓存的设置与此类似:
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
数据源使用相同的函数获取一个未使用的视图控制器:
extension MyPageViewController: UIPageViewControllerDataSource
func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController viewController: UIViewController) -> UIViewController?
let nextViewController = unusedViewController()
// Configure the next view controller for display
// ...
return nextViewController
【讨论】:
这是目前水平浏览数据库中记录的最佳方式(每页一条记录)吗?在 android 中,它已经以ViewPager
的形式完成,它会为您管理重用。
谢谢。我正在使用if let someUnusedViewController = reuseableViewControllers.first(where: $0.parentViewController == nil )
,这可能效率更高。我使用的是数组而不是 Set。我在 ios 12.1 上发现代码只构建了三个视图控制器。
这是一个非常聪明的解决方案。虽然我有两个问题,如果使用 set 你如何找出你所在页面的索引以避免创建轮播效果。同样作为一个普遍问题,在这种情况下使用 UIPageViewController 比使用全尺寸 collectionViewCell 有什么优势?
您需要单独跟踪索引,例如,将viewController
向下转换为具有index
属性的自定义UIViewController
子类。您的第二个问题太宽泛,无法在评论中回答。您可能需要先阅读UIPageViewController
和UICollectionView
的文档,如果还有什么不清楚的地方,请发布一个新的、更具体的问题。
谢谢。请问,如何在 UIPageViewController 中保留 UI 状态?比如第2页有滚动位置X的UICollectionView,当我们滑回第2页时,如何恢复UICollectionView的X位置?【参考方案2】:
您可以使用ACReuseQueue 来实现您想要的。它提供了一个用于重用视图控制器的队列。您可以使用 UIPageViewController 数据源方法将 VC 从重用队列中出列。棘手的部分是知道何时将它们放回重用队列。 UIPageViewController 没有提供任何方法来知道何时发生这种情况,但是有一种方法。 UIPageViewController 是一个容器 VC,它使用 VC 包含 API 添加和删除其子视图控制器。 如果从 UIPageViewController 中删除它,您的 VC 将收到以 nil 作为参数的 didMoveToParentViewController:。使用此方法将自己重新添加到队列中。
【讨论】:
"棘手的部分是知道何时将它们放回重用队列。UIPageViewController 没有提供任何方法来知道何时发生这种情况,但有办法。"这终于让它点击了,谢谢!以上是关于如何使 UIPageViewController 像 tableview 重用单元一样重用控制器?的主要内容,如果未能解决你的问题,请参考以下文章
使用 UIPageViewController 使 UI 滚动视图滚动
如何使用现有 UIPageViewController 的按钮以编程方式滑动视图