Swift複数のView Controllerを備えたアプリでUIPageViewController
を利用しようとしています。ストーリーボードに2つのView Controllerがあります(firstViewController
とsecondViewController
両方とも独自の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はシミュレーターへの接続を失います。何が起きているのかよくわかりません。
OK、わかりました。ページビューコントローラーがルートになり、すべてを処理する必要があるため、iiFreemanがデリゲートおよびデータソースプロトコルを提案および準拠するようにサブクラス化してUIPageViewController
asにしました。次に、viewDidLoad
にコントローラーをセットアップし、デリゲートメソッドとデータソースメソッドを実装しました。ストーリーボード識別子の配列と、その配列の現在のインデックスを追跡するためのプロパティストアを追加しました。また、インデックスを指定して正しいView Controllerを返すヘルパーメソッドを追加しました。ページビューコントローラーがすべてを処理していたため、他のtableView
コントローラーサブクラスには何も必要ありませんでした。私が気づいたことの1つは、tableViewController
sが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
}
}
必ずFirstViewController-ストーリーボードの初期ビューコントローラー
カスタムUIPageViewControllerサブクラスをストーリーボードに追加し、初期としてマークし、内部ですべての作業を行い、UIPageViewControllerサブクラスのstoryboardIDでページコントローラーメンバーをインスタンス化し、別のクラス内で同じことを行います
このコードは2つのViewController
でのみ機能することに注意してください。さらに使用する予定がある場合は、行を変更する必要があります。
self.index = self.index + 1
前後の呼び出しで見つかりました:
self.index = index + 1
現在のViewController
インデックスを呼び出します。