iOS Swift:UIPageViewController-以编程方式翻页

iOS Swift:UIPageViewController-以编程方式翻页,ios,swift,uiviewcontroller,uipageviewcontroller,Ios,Swift,Uiviewcontroller,Uipageviewcontroller,我有一个UIPageViewController,当我们向左或向右滑动翻页时,它可以正常工作 class ViewController: UIViewController, UIPageViewControllerDataSource { ... } 现在我还打算在页面上提供上一页/下一页按钮,这样就可以通过单击这些按钮来打开页面 如何以编程方式触发向左/向右滑动行为或翻页 注 这是Swift语言的问题,而不是Objective-C。使用此功能并为所需动画设置过渡样式 以下是这方面的快速实

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

class ViewController: UIViewController, UIPageViewControllerDataSource {
...
}
现在我还打算在页面上提供上一页/下一页按钮,这样就可以通过单击这些按钮来打开页面

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



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

使用此功能并为所需动画设置过渡样式


以下是这方面的快速实施:

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?()
                })
            }
        }
    }
}
private func slideToPage(索引:Int,完成:(()->Void)?){
let count=//获取ViewController数量的函数
如果索引<计数{
如果索引>当前页面索引{
如果让vc=viewControllerAtIndex(索引){
self.pageViewController.SetViewController([vc],方向:UIPageViewControllerNavigationDirection.Forward,动画:true,完成:{(完成)->Void in
self.currentPageIndex=索引
完成?()
})
}
}如果索引Void in
self.currentPageIndex=索引
完成?()
})
}
}
}
}

viewControllerAtIndex(index:Int)->UIViewController?
是我自己的功能,用于获取要滑动到的正确视图控制器。

通常不需要摆弄页面索引之类的东西。很可能您已经实现了一个
数据源: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的内置手势触发的页面。

Swift 3版本的(对
已设置动画的
参数稍作调整,因为我需要在默认情况下设置动画,但仍在函数中使用一个参数),以防任何人需要它:

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)
    }

}

如果有人想使用定义好的协议以编程的方式导航和更改视图控制器,请将此内容保留在这里

@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()
       self.dataSource = self
    }

    // 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()
           self.dataSource = self
        }

         @IBAction func goNextPage(_ sender: Any) {
            // Can be any number but not outside viewControllerList bounds 
            delegate.goNextPage!(fowardTo: 2)
         }
    }

下面是学员的swift 4实施

因为我也使用UIPageViewControllerDelegate,大多数setViewController解决方案都没有调用委托方法

感谢您对该代表的评论

// 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) })
}

JordanC>的可能副本我需要在点击按钮时翻页-那么我如何使用上述功能?@Jasper制作一个UIButton,点击后,您可以确定UIPageViewController中下一页是哪个页面,并将该页面传递到SetViewController方法。我不知道为什么,但我得到了正确的页面,但如果我调用此方法en没有任何变化。我很难想出如何使用您的想法更新
PresentationIndexFormageViewController
。在我的
pageItemViewController
上,我声明了一个名为
itemIndex
的变量。如何在这个扩展中设置它?我使用了func goToNextPage()使用计时器-那么我如何使用此方法使用计时器滚动到下一页?这是我的问题Lifesaver的链接!!!非常感谢。我将发布Swift 3版本仅供将来参考。做得好,以我的拙见演示了UPPageViewController中的一个缺口。:)快速提示:此方法似乎不会触发UIPageViewControllerDelegate(:didFinishAnimating),但在使用手势进行分页时会调用它,这与其说是一个功能,不如说是一个bug。非常感谢!很高兴它有帮助@WilliamT.mallardi如果您正在更新代理中的点,您可能希望使用此代码来完成(而不是nil):
{completed in self.delegate?.pageViewController?(self,didffinishanimating:true,previousViewControllers:[],transitionCompleted:completed)}
@Recusiwe检查yoursHi上方的注释,谢谢你写这篇文章,这可能是一个愚蠢的问题,但是一旦我创建了UIPageViewController的扩展,我是否应该在类PageController上调用它:UIPageViewController?(PageController是名称)。如果我尝试这样做:PageController.goToNextPage(动画:true),我得到:实例成员“goToNextPage”不能用于类型“PageController”;您是否打算改为使用此类型的值?
currentPageIndex
来自何处?
currentPageIndex
是您定义的本地变量,以便跟踪当前页面。