【问题标题】:iOS Swift: UIPageViewController - Turning page programmaticallyiOS Swift:UIPageViewController - 以编程方式翻页
【发布时间】:2015-05-27 18:02:14
【问题描述】:

我有一个 UIPageViewController,当我们向左或向右滑动翻页时,它可以正常工作。

class ViewController: UIViewController, UIPageViewControllerDataSource {
...
}

现在我打算在页面上也提供上一个/下一个按钮,以便通过单击这些按钮来翻页。

如何触发左右滑动行为或以编程方式翻页?


注意

这是 Swift 语言的问题,而不是 Objective-C。

【问题讨论】:

标签: ios swift uiviewcontroller uipageviewcontroller


【解决方案1】:

通常没有必要摆弄页面索引等等。您可能已经在实现一个dataSource: UIPageViewControllerDataSource,它包含了显示上一个或下一个 ViewController 所需的所有内容。

Swift 5 示例:

extension UIPageViewController {

    func goToNextPage() {
       guard let currentViewController = self.viewControllers?.first else { return }
       guard let nextViewController = dataSource?.pageViewController( self, viewControllerAfter: currentViewController ) else { return }
       setViewControllers([nextViewController], direction: .forward, animated: false, completion: nil)
    }

    func goToPreviousPage() {
       guard let currentViewController = self.viewControllers?.first else { return }
       guard let previousViewController = dataSource?.pageViewController( self, viewControllerBefore: currentViewController ) else { return }
       setViewControllers([previousViewController], direction: .reverse, animated: false, completion: nil)
    }

}

这样您就可以保证您要转换到的页面正是PageViewController's 内置手势将触发的页面。

【讨论】:

  • 我很难弄清楚如何使用您的想法更新presentationIndexForPageViewController。在我的pageItemViewController 上,我声明了一个名为itemIndex 的变量。我将如何在此扩展程序中设置它?
  • 我使用带有计时器的 func goToNextPage() - 那么如何使用此方法滚动到带有计时器的下一页呢?这是我的问题的链接stackoverflow.com/questions/45025088/…
  • 救命稻草!!!非常感谢。我将发布 Swift 3 版本以供将来参考。
  • 干得好,以我的拙见展示了 UPPageViewController 中的差距。 :)
  • 快速说明:此方法似乎不会触发 UIPageViewControllerDelegate(:didFinishAnimating,但在使用手势分页时确实会调用它,这更像是一个错误而不是我怀疑的功能。
【解决方案2】:

Swift 3 版本的SuitedSloth 的答案(对animated 参数进行了小调整,因为我需要它在默认情况下进行动画处理,但仍然在函数中使用参数) 以防万一有人需要:

extension UIPageViewController {

    func goToNextPage(animated: Bool = true) {
        guard let currentViewController = self.viewControllers?.first else { return }
        guard let nextViewController = dataSource?.pageViewController(self, viewControllerAfter: currentViewController) else { return }
        setViewControllers([nextViewController], direction: .forward, animated: animated, completion: nil)
    }

    func goToPreviousPage(animated: Bool = true) {
        guard let currentViewController = self.viewControllers?.first else { return }
        guard let previousViewController = dataSource?.pageViewController(self, viewControllerBefore: currentViewController) else { return }
        setViewControllers([previousViewController], direction: .reverse, animated: animated, completion: nil)
    }

}

【讨论】:

  • 非常感谢!
  • 很高兴它帮助了@WilliamT.Mallard
  • 如果您要更新委托中的点,您可能希望使用此代码来完成(而不是 nil):{ completed in self.delegate?.pageViewController?(self, didFinishAnimating: true, previousViewControllers: [], transitionCompleted: completed) }
  • @Recusiwe 检查你上面的评论
  • 嗨,谢谢你写这篇文章,这可能是一个愚蠢的问题,但是一旦我创建了 UIPageViewController 的扩展,我不应该能够在类 PageController 上调用它吗:UIPageViewController? (PageController 是名称)。如果我尝试这样做:PageController.goToNextPage(animated: true),我得到:实例成员 'goToNextPage' 不能用于类型 'PageController';您的意思是改用这种类型的值吗?
【解决方案3】:

使用此功能并为您想要的动画设置过渡样式。

【讨论】:

  • JordanC> 我需要点击一个按钮来翻页 - 那么我如何使用上述功能呢?
  • @Jasper 创建一个 UIButton,当它被点击时,你会在你的 UIPageViewController 中找出下一个页面,然后将该页面传递给 setViewControllers 方法。
  • 我不知道为什么,但我得到了正确的页面,但如果我调用此方法,则没有任何变化。
【解决方案4】:

这里也是带有代表的 swift 4 实现。

由于我也使用 UIPageViewControllerDelegate,并且大多数 setViewController 解决方案都没有调用委托方法。

感谢Andrew Duncan's 对代表的评论。

// Functions for clicking next and previous in the navbar, Updated for swift 4
@objc func toNextArticle(){
    guard let currentViewController = self.viewControllers?.first else { return }

    guard let nextViewController = dataSource?.pageViewController( self, viewControllerAfter: currentViewController ) else { return }

    // Has to be set like this, since else the delgates for the buttons won't work
    setViewControllers([nextViewController], direction: .forward, animated: true, completion: { completed in self.delegate?.pageViewController?(self, didFinishAnimating: true, previousViewControllers: [], transitionCompleted: completed) })
}

@objc func toPreviousArticle(){
    guard let currentViewController = self.viewControllers?.first else { return }

    guard let previousViewController = dataSource?.pageViewController( self, viewControllerBefore: currentViewController ) else { return }

    // Has to be set like this, since else the delgates for the buttons won't work
    setViewControllers([previousViewController], direction: .reverse, animated: true, completion:{ completed in self.delegate?.pageViewController?(self, didFinishAnimating: true, previousViewControllers: [], transitionCompleted: completed) })
}

【讨论】:

    【解决方案5】:

    这是一个快速的实现:

    private func slideToPage(index: Int, completion: (() -> Void)?) {
        let count = //Function to get number of viewControllers
        if index < count {
            if index > currentPageIndex {
                if let vc = viewControllerAtIndex(index) {
                    self.pageViewController.setViewControllers([vc], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: { (complete) -> Void in
                        self.currentPageIndex = index
                        completion?()
                    })
                }
            } else if index < currentPageIndex {
                if let vc = viewControllerAtIndex(index) {
                    self.pageViewController.setViewControllers([vc], direction: UIPageViewControllerNavigationDirection.Reverse, animated: true, completion: { (complete) -> Void in
                        self.currentPageIndex = index
                        completion?()
                    })
                }
            }
        }
    }
    

    viewControllerAtIndex(index: Int) -&gt; UIViewController? 是我自己的函数,可以让正确的视图控制器滑动到。

    【讨论】:

    • currentPageIndex 来自哪里?
    • currentPageIndex 是您定义的本地变量,以便您可以跟踪当前页面。
    【解决方案6】:

    如果有人想使用定义的协议来导航和以编程方式更改视图控制器,请把它留在这里。

    @objc protocol AppWalkThroughDelegate {
      @objc optional func goNextPage(forwardTo position: Int)
      @objc optional func goPreviousPage(fowardTo position: Int)
    }
    

    使用上述协议并确认根 UIPageViewController 来管理视图控制器之间的导航。

    下面的例子:

    class AppWalkThroughViewController: UIPageViewController, UIPageViewControllerDataSource, AppWalkThroughDelegate {
    
        // Add list of view controllers you want to load
    
        var viewControllerList : [UIViewControllers] = {
           let firstViewController = FirstViewController()
           let secondViewController = SecondViewController() 
           // Assign root view controller as first responder
           secondViewController.delegate = self  
    
           let thirdViewController = ThirdViewController() 
           
        }
    
        override func viewDidLoad() {
           super.viewDidLoad()
        }
        
        // Navigate to next page 
        func goNextPage(fowardTo position: Int) {
           let viewController = self.viewControllerList[position]
           setViewControllers([viewController], direction: 
           UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
        }
    
        }
    

    一旦实现了所有这些,需要使 UIPageViewController 移动到下一页或上一页的子视图控制器可以通过将特定数字传递给委托属性来使用 AppWalkThroughDelegate 方法。

    以下示例:按下按钮后调用委托方法

        class SecondViewController: UIViewController {
           
            var delegate: AppWalkThroughDelegate!
            
            override func viewDidLoad() {
               super.viewDidLoad()
            }
    
             @IBAction func goNextPage(_ sender: Any) {
                // Can be any number but not outside viewControllerList bounds 
                delegate.goNextPage!(fowardTo: 2)
             }
        }
    

    【讨论】:

    • 第二个例子,为什么要设置self.dataSource = self
    • 可能是一个错误,但不应该在那里,感谢您指出这一点。 @JDerbs
    猜你喜欢
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 2013-02-01
    • 1970-01-01
    • 2016-05-26
    • 2016-10-29
    • 2012-03-30
    • 1970-01-01
    相关资源
    最近更新 更多