UIPageViewControllerで現在のページを取得する場合の注意
複数のViewをページめくりの様にして使えるUIPageViewController
公式ドキュメント。
Apple Developer Documentation
多分ググればかなりの数が出てくる。
今何ページ目なのかが知りたい事はよくある
ページ番号を振るとか、ページごとに固有の処理をさせたいとか、UIPageControlのcurrentPageに設定する為とか、そんな目的で、今何ページ目かが知りたい事がよくある。
なぜか正しい値を示さない
以下のように、viewControllerAtIndexの中で描画されたページ(今のページ)のindexを記録するようにしたところ、返ってくる値がおかしい。
2ページ目なのに3とか返ってくる。
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index { currentPage = index; // currentPageに今何ページ目かをセットしてクラス内で使えるようにする /* ~~ 各ページ用のviewController作る ~~ */ return viewController; }
UIPageViewControllerは今のページとその前後のページを先読みしているため
ドキュメントを見ると、どうもUIPageViewControllerは動きをサクサクさせる為に、今のページとその前後のページをあらかじめ作っておくらしい。
そのため、1ページ目から2ページ目にいく時に、裏では3ページ目もよんでいてcurrentPageに3が入ってしまっていた。
ちなみに、前後なので1ページ目も先読み対象になるけど、既に作成されているページは読み込まない。逆に言うと廃棄もしない。
廃棄されるのは3ページ目になった時。
今activeなページを取得する為には
で、色々調べた結果、以下のようなメソッドが使えるとの事。
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed { // ContentViewControllerはあらかじめ作っている各ページ用のクラス // ContentViewControllerにはcurrentIndexというプロパティを持たせていて、ページ作成時にセットするようにする ContentViewController *currentViewController = [pageViewController.viewControllers objectAtIndex:0]; currentPage = currentViewController.currentIndex; }
スクロールモーションが終わったタイミングをフックに、viewControllersを取得する。
viewControllersには今前面に出ているviewControllerとその親たちが入っているので先頭(子供)を取得する。
一瞬ハマりかけたけど、解決。