Work Records

日々の作業記録です。ソフトウェアエンジニアリング全般から、趣味の話まで。

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とその親たちが入っているので先頭(子供)を取得する。


一瞬ハマりかけたけど、解決。