到目前为止,我遇到的大多数 UIPageViewController
教程都会在滑动到所需页面时动态创建 UIViewController
。
UIPageViewController 示例,未经优化
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var contentView: UIView!
let dataSource = ["View Controller One", "View Controller Two", "View Controller Three", "View Controller Four"]
var currentViewControllerIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
configurePageViewController()
}
func configurePageViewController() {
guard let pageViewController = storyboard?.instantiateViewController(withIdentifier: String(describing: CustomPageViewController.self)) as? CustomPageViewController else {
return
}
pageViewController.delegate = self
pageViewController.dataSource = self
addChild(pageViewController)
pageViewController.didMove(toParent: self)
pageViewController.view.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(pageViewController.view)
let views: [String: Any] = ["pageView": pageViewController.view]
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[pageView]-0-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[pageView]-0-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: views))
guard let startingViewController = detailViewControllerAt(index: currentViewControllerIndex) else {
return
}
pageViewController.setViewControllers([startingViewController], direction: .forward, animated: true)
}
func detailViewControllerAt(index: Int) -> DataViewController? {
if index >= dataSource.count || dataSource.count == 0 {
return nil
}
guard let detailViewController = storyboard?.instantiateViewController(withIdentifier: String(describing: DataViewController.self)) as? DataViewController else {
return nil
}
detailViewController.index = index
detailViewController.displayText = dataSource[index]
return detailViewController
}
}
extension ViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
print ("presentationIndex \(currentViewControllerIndex)")
return currentViewControllerIndex
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
print ("presentationCount \(dataSource.count)")
return dataSource.count
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let dataViewController = viewController as? DataViewController
guard var currentIndex = dataViewController?.index else {
return nil
}
print ("viewControllerBefore \(currentIndex)")
if (currentIndex == 0) {
return nil
}
currentIndex -= 1
currentViewControllerIndex = currentIndex
return detailViewControllerAt(index: currentIndex)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let dataViewController = viewController as? DataViewController
guard var currentIndex = dataViewController?.index else {
return nil
}
print ("viewControllerBefore \(currentIndex)")
if currentIndex == dataSource.count-1 {
return nil
}
currentIndex += 1
currentViewControllerIndex = currentIndex
return detailViewControllerAt(index: currentIndex)
}
}
但是,我几乎没有看到任何关于如何优化 UIPageViewController
来处理大量页面的示例。
为每个页面重新创建新的 UIViewController
似乎不是最佳解决方案,因为它会很慢。它还会占用不必要的内存空间,因为大部分屏幕外的 UIViewController 是不可见的。
我们怎样才能拥有类似于 tableView.dequeueReusableCell(withIdentifier:for:)
的东西?
我们可以重用那些之前创建的、当前不可见的UIViewController
吗?
非常感谢任何有关如何正确实现这一点的代码示例或教程资源。谢谢。
最佳答案
动态创建 Controller 可能会导致一些故障,因此我通常有一些像 var viewControllers: [UIViewController]
这样的数组来存储我的页面
并实现UIPageViewControllerDataSource
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let index = viewControllers.firstIndex(of: viewController), index > 0 else {
return nil
}
currentViewControllerIndex = index - 1
return viewControllers[currentViewControllerIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let index = viewControllers.firstIndex(of: viewController), index < viewControllers.count - 1 else {
return nil
}
currentViewControllerIndex = index + 1
return viewControllers[currentViewControllerIndex]
}
为了减少内存使用,您可以在页面更改时释放 View Controller 的 View :
var currentViewControllerIndex = 0 {
didSet {
let range = currentViewControllerIndex - 1...currentViewControllerIndex + 1
for (offset, element) in viewControllers.enumerated() {
if range ~= offset {
element.loadViewIfNeeded()
} else {
element.view = nil
}
}
}
}
关于ios - 如何优化 UIPageViewController 使其具有类似于 tableView.dequeueReusableCell(withIdentifier :for:)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57175319/