web-dev-qa-db-ja.com

UIPageViewControllerをSwiftおよび複数のView Controllerとともに使用する

Swift複数のView Controllerを備えたアプリでUIPageViewControllerを利用しようとしています。ストーリーボードに2つのView Controllerがあります(firstViewControllersecondViewController両方とも独自のNavigation Controllerに埋め込まれています。ストーリーボード識別子は「FirstViewController」と「SecondViewController」です。また、ストーリーボードにはidentifierPageViewコントローラーと設定を持つPage View Controllerもあります属性インスペクターでスクロールする水平および遷移スタイルへのナビゲーションFirstViewControllerはアプリのルートビューコントローラーです

firstViewControllerをPage View Controllerの最初のページにしたいので、次のようにクラスを記述しました。

import Foundation
import UIKit

class FirsttViewController: UITableViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate  {

    override func viewDidLoad() {

        let pageViewController: PageViewController = self.storyboard.instantiateViewControllerWithIdentifier("PageViewController") as PageViewController

        pageViewController.delegate = self

        var viewControllers: [UIViewController] = [self]

        pageViewController.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
        pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)

        self.addChildViewController(pageViewController)
        self.view.addSubview(pageViewController.view)
        pageViewController.didMoveToParentViewController(self)


    }
    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {


        let secondViewController: SecondViewController = self.storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as SecondViewController


        return secondViewController
    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        return nil
    }

    func presentationCountForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 2
    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 0
    }
}

SecondViewControllerのファイルは次のようになります。

import Foundation
import UIKit

class SecondViewController: UITableViewController, UIPageViewControllerDataSource {

    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {

        return nil
    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        let firstViewController: FirstViewController = self.storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as FirstViewController
        return firstViewController
    }

}

ただし、アプリを実行すると、Page View Controllerがないようです。 firstViewControllerと表示されているだけです。ドットやページなどはありません。 Objective-Cのチュートリアルをいくつか見つけましたが、それらはすべて、すべてのページに1つのView Controllerを使用してカバーし、pageViewのページではないルートView Controllerを持っているため、あまり役に立ちませんでした。 View ControllerをクリックしてドラッグするだけのtabBarControllerを使用するようなものになることを期待していましたが、残念ながらそうではありません。以前にこれらのいずれかで作業したことがないと言ったように、私はちょっと迷っています。

更新:

iiFreemanの提案に従って、UIPageViewControllerをサブクラス化し、ストーリーボードファイルのルートにしました。以下はサブクラスです

import Foundation
import UIKit
class PageViewController: UIPageViewController {

    override func viewDidLoad() {

        let startingViewController = self.storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as FirstViewController

        self.dataSource = startingViewController
        var viewControllers: [UIViewController] = [startingViewController]

        self.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)



    }

}

ただし、現在はアプリが黒い画面でハングし、最終的にXcodeはシミュレーターへの接続を失います。何が起きているのかよくわかりません。

17
Stone Preston

OK、わかりました。ページビューコントローラーがルートになり、すべてを処理する必要があるため、iiFreemanがデリゲートおよびデータソースプロトコルを提案および準拠するようにサブクラス化してUIPageViewControllerasにしました。次に、viewDidLoadにコントローラーをセットアップし、デリゲートメソッドとデータソースメソッドを実装しました。ストーリーボード識別子の配列と、その配列の現在のインデックスを追跡するためのプロパティストアを追加しました。また、インデックスを指定して正しいView Controllerを返すヘルパーメソッドを追加しました。ページビューコントローラーがすべてを処理していたため、他のtableViewコントローラーサブクラスには何も必要ありませんでした。私が気づいたことの1つは、tableViewControllersがNavigation Controllerに埋め込まれていたためです。実際には、Page View ControllerはtableViewコントローラーではなくNavigation Controllerを表示する必要がありました。以下は私の実装です:

import Foundation
import UIKit

class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    var index = 0
    var identifiers: NSArray = ["FirstNavigationController", "SecondNavigationController"]
    override func viewDidLoad() {

        self.dataSource = self
        self.delegate = self

        let startingViewController = self.viewControllerAtIndex(self.index)
        let viewControllers: NSArray = [startingViewController]
        self.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)



    }

    func viewControllerAtIndex(index: Int) -> UINavigationController! {

        //first view controller = firstViewControllers navigation controller
        if index == 0 {

            return self.storyboard.instantiateViewControllerWithIdentifier("FirstNavigationController") as UINavigationController

        }

        //second view controller = secondViewController's navigation controller
        if index == 1 {

            return self.storyboard.instantiateViewControllerWithIdentifier("SecondNavigationController") as UINavigationController
        }

        return nil
    }
    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {

        let identifier = viewController.restorationIdentifier
        let index = self.identifiers.indexOfObject(identifier)

        //if the index is the end of the array, return nil since we dont want a view controller after the last one
        if index == identifiers.count - 1 {

            return nil
        }

        //increment the index to get the viewController after the current index
        self.index = self.index + 1
        return self.viewControllerAtIndex(self.index)

    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        let identifier = viewController.restorationIdentifier
        let index = self.identifiers.indexOfObject(identifier)

        //if the index is 0, return nil since we dont want a view controller before the first one
        if index == 0 {

            return nil
        }

        //decrement the index to get the viewController before the current one
        self.index = self.index - 1
        return self.viewControllerAtIndex(self.index)

    }


    func presentationCountForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return self.identifiers.count
    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 0
    }

}

この投稿は私を大いに助けてくれました

33
Stone Preston

必ずFirstViewController-ストーリーボードの初期ビューコントローラー

カスタムUIPageViewControllerサブクラスをストーリーボードに追加し、初期としてマークし、内部ですべての作業を行い、UIPageViewControllerサブクラスのstoryboardIDでページコントローラーメンバーをインスタンス化し、別のクラス内で同じことを行います

1
iiFreeman

このコードは2つのViewControllerでのみ機能することに注意してください。さらに使用する予定がある場合は、行を変更する必要があります。

self.index = self.index + 1

前後の呼び出しで見つかりました:

self.index = index + 1

現在のViewControllerインデックスを呼び出します。

1