web-dev-qa-db-ja.com

iOS Swift:UIPageViewController-プログラムでページをめくる

UIPageViewControllerがあります。これは、ページをめくるために左または右にスワイプしたときに正常に動作します。

class ViewController: UIViewController, UIPageViewControllerDataSource {
...
}

ここで、これらのボタンをクリックしてページをめくることができるように、ページにも前/次ボタンを提供する予定です。

左右にスワイプする動作をトリガーするにはどうすればよいですかORプログラムでページをめくる?


注意

これは、Objective-CではなくSwift言語に対する質問です。

23
Jasper

この関数を使用して、必要なアニメーションの切り替えスタイルを設定します。

enter image description here

enter image description here

9
JordanC

通常、ページインデックスとその他のことをいじる必要はありません。 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の組み込みジェスチャでトリガーされるものとまったく同じであることが保証されます。

47
SuitedSloth

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

}
20
Gligor

こちらも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) })
}
7
Vasco

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を取得するための独自の関数です。

5
Swinny89

ここでこれを省略すると、定義されたプロトコルを使用して、ビューコントローラーをプログラムで移動および変更することができます。

@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)
         }
    }
1
Sharkes Monken