在 UIPageViewControllers (Swift) 中预加载所有 UIViewControllers

Posted

技术标签:

【中文标题】在 UIPageViewControllers (Swift) 中预加载所有 UIViewControllers【英文标题】:Pre-load all UIViewControllers in UIPageViewControllers (Swift) 【发布时间】:2017-05-25 02:16:43 【问题描述】:

我目前在情节提要中有 3 个 UIViewController,我将它们连接到一个带有 scrollView 的 UIPageViewController。但是,由于没有在 PageViewController 中预加载所有 UIViewController,我在初始化中心 UIViewController 上的应用程序时遇到了一些问题。当用户第一次打开应用程序 viewDidLoad 时,我使用滚动视图 contentOffset 显示中心 ViewController。

我已经附上了我在这里使用的代码:

    var currentIndex = 0
    var mainScrollView = UIScrollView()
    lazy var ViewControllerArray: [UIViewController] = 
        return [self.ViewControllerInstance(name: "RightVC"),
                self.ViewControllerInstance(name: "CenterVC"),
                self.ViewControllerInstance(name: "LeftVC")]

    ()

    private func ViewControllerInstance(name: String) -> UIViewController

        return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: name)

    


    override func viewDidLoad() 
        super.viewDidLoad()
        self.dataSource = self
        self.delegate = self
        if let CenterViewController = ViewControllerArray.first 
            setViewControllers([CenterViewController] , direction: .reverse, animated: false, completion: nil)
        
    

    override func viewDidAppear(_ animated: Bool) 
        mainScrollView = view.subviews.filter  $0 is UIScrollView .first as! UIScrollView
        mainScrollView.delegate = self
        mainScrollView.contentOffset.x = self.view.bounds.size.width * 2



    




    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? 
        guard let ViewControllerIndex = ViewControllerArray.index(of: viewController) else 
            return nil
        

        let PreviousIndex = ViewControllerIndex - 1
        currentIndex = ViewControllerIndex
        guard PreviousIndex >= 0 else 
            return nil
        
        guard ViewControllerArray.count > PreviousIndex else 
            return nil

        

        return ViewControllerArray[PreviousIndex]
    


    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? 
        guard let ViewControllerIndex = ViewControllerArray.index(of: viewController) else 
            return nil
        

        let NextIndex = ViewControllerIndex + 1
        currentIndex = ViewControllerIndex
        guard NextIndex < ViewControllerArray.count else 
            return nil
        
        guard ViewControllerArray.count > NextIndex else 
            return nil

        

        return ViewControllerArray[NextIndex]

    
    // Control bounce @ DidScroll & EndDragging
    func scrollViewDidScroll(_ scrollView: UIScrollView) 
        let lastPosition = scrollView.contentOffset.x
        if (currentIndex == ViewControllerArray.count - 1) && (lastPosition > scrollView.frame.width) 
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)

         else if currentIndex == 0 && lastPosition < scrollView.frame.width 
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
        
    
    // ^^
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) 
        let lastPosition = scrollView.contentOffset.x
        if (currentIndex == ViewControllerArray.count - 1) && (lastPosition > scrollView.frame.width) 
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
         else if currentIndex == 0 && lastPosition < scrollView.frame.width 
            scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
        

    

【问题讨论】:

【参考方案1】:

更新: 我使用了一个变量 IntialOpen 作为系统的布尔值来了解应用程序之前是否打开过,并且我还在公共函数中添加了 If/else 语句。

public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? 
        guard let ViewControllerIndex = ViewControllerArray.index(of: viewController) else 
            return nil
        
        let PreviousIndex = ViewControllerIndex - 1

        if !initialOpen 
            currentIndex = ViewControllerIndex
        else
            currentIndex = ViewControllerIndex + 1
            initialOpen = false
        
        guard PreviousIndex >= 0 else 
            return nil
        
        guard ViewControllerArray.count > PreviousIndex else 
            return nil
        
        return ViewControllerArray[PreviousIndex]
    


    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? 
        guard let ViewControllerIndex = ViewControllerArray.index(of: viewController) else 
            return nil
        

        let NextIndex = ViewControllerIndex + 1


        if !initialOpen 
            currentIndex = ViewControllerIndex
        else
            currentIndex = ViewControllerIndex + 1
            initialOpen = false
        
        guard NextIndex < ViewControllerArray.count else 
            return nil
        
        guard ViewControllerArray.count > NextIndex else 
            return nil

        

        return ViewControllerArray[NextIndex]

    

如果这是第一次启动应用程序,这几乎是通过强制它在第二页上打开来实现的。

【讨论】:

以上是关于在 UIPageViewControllers (Swift) 中预加载所有 UIViewControllers的主要内容,如果未能解决你的问题,请参考以下文章

UIPageViewControllers UIPageControl 在过渡期间出现故障

使用 UIPageViewController 创建网格/地图

2 UIPageViewController 手势冲突

如何设置 UIPageViewController(分页类型)手势委托

UIPageViewController 结合安全区

UIPageViewController 在我的 UIImage 底部创建一个边框以及如何摆脱它