UIPageViewControllerがあります。これは、ページをめくるために左または右にスワイプしたときに正常に動作します。
class ViewController: UIViewController, UIPageViewControllerDataSource {
...
}
ここで、これらのボタンをクリックしてページをめくることができるように、ページにも前/次ボタンを提供する予定です。
左右にスワイプする動作をトリガーするにはどうすればよいですかORプログラムでページをめくる?
これは、Objective-CではなくSwift言語に対する質問です。
この関数を使用して、必要なアニメーションの切り替えスタイルを設定します。
通常、ページインデックスとその他のことをいじる必要はありません。 dataSource: UIPageViewControllerDataSource
を既に実装している可能性があります。これには、前または次のViewControllerを表示するために必要なすべてが含まれています。
Swift 2.2の例:
extension UIPageViewController {
func goToNextPage(){
guard let currentViewController = self.viewControllers?.first else { return }
guard let nextViewController = dataSource?.pageViewController( self, viewControllerAfterViewController: 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, viewControllerBeforeViewController: currentViewController ) else { return }
setViewControllers([previousViewController], direction: .Reverse, animated: false, completion: nil)
}
}
これにより、移行先のページが、PageViewControllerの組み込みジェスチャでトリガーされるものとまったく同じであることが保証されます。
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)
}
}
こちらも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) })
}
Swiftこの実装:
_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) -> UIViewController?
は、スワイプ先の正しいView Controllerを取得するための独自の関数です。
ここでこれを省略すると、定義されたプロトコルを使用して、ビューコントローラーをプログラムで移動および変更することができます。
@objc protocol AppWalkThroughDelegate {
@objc optional func goNextPage(forwardTo position: Int)
@objc optional func goPreviousPage(fowardTo position: Int)
}
上記のプロトコルを使用し、ルートUIPageViewControllerを確認して、View Controller間のナビゲーションを管理します。
以下の例:
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を次または前のページに移動する必要がある子View Controllerは、デリゲートプロパティに特定の番号を渡すことで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)
}
}