0

これで一日中主要なヘッドスクラッチャー:-(

デリゲートメソッドを起動していないように見えるUIPageViewControllerのインスタンスがあります。

-(UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
                  spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation

UIPageViewControllerを表示するさまざまな方法を試しましたが、1つの例外を除いて、正しく機能しているように見えるプログラムによるアプローチ(ストーリーボードではなく)に落ち着きました... iPadを回転させて背骨を横向きにすると、背骨が真ん中に表示されません。期待通りのポイント。デリゲートメソッドが呼び出されない理由がわかりません。

コードの説明(たとえば簡略化)

次の3つのクラスを検討してください。

  • RootViewController-アプリの起動時に読み込まれます
  • PageViewController-ユーザーの開始時にRootViewControllerによってロードされます
  • PageContentViewController-ページが必要なときにPageViewControllerによってロードされます

かなり自明です。RootViewControllerは、起動時にアプリによって読み込まれます。ユーザーがこのビューコントローラーのビュー内の画像をタップすると(雑誌の表紙が雑誌を開くと考えてください)、次のようにPageViewControllerが起動します。

PageViewController *pvc = [[PageViewController alloc] initWithNibName:@"PageView" 
                                           bundle:[NSBundle mainBundle]];
pvc.view.frame = self.view.bounds;
[self.view addSubview:pvc.view];

実際のアプリには、トランジションをすべてうまく行うためのアニメーションなどがありますが、基本的には、PageViewControllerのビューが読み込まれ、フルスクリーンになります。

PageViewController

これが主力です(関連するメソッドのみが示されています)。私はグーグルの無限の世界からの様々な例を試し、アップルのドキュメントから直接書いた...

@interface PageViewController : UIViewController <UIPageViewControllerDelegate, UIPageViewControllerDataSource>

@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSMutableArray *modelArray;

@end


@implementation TXCategoryController

-(void)viewDidLoad 
{

    [super viewDidLoad];

    // Simple model for demo
    self.modelArray = [NSMutableArray alloc] init];

    for (int i=1; i<=20; i++)
        [self.modelArray addObject:[NSString stringWithFormat:@"Page: %d", i]];

    self.pageViewController = [[UIPageViewController alloc] 
               initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
                 navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];

    self.pageViewController.delegate = self;
    self.pageViewController.dataSource = self;

    PageContentViewController *startupVC = [[PageContentViewController alloc] initWithNibName:@"PageContent" bundle:nil];

    startupVC.pageLabel = [self.modelArray objectAtIndex:0];

    [self.pageViewController setViewControllers:[NSArray arrayWithObject:startupVC]
                                      direction:UIPageViewControllerNavigationDirectionForward
                                       animated:NO
                                     completion:nil];

    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];
    [self.pageViewController didMoveToParentViewController:self];
    self.pageViewController.view.frame = self.view.bounds;
    self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;

}

-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController
  viewControllerBeforeViewController:(UIViewController *)viewController
{
    // Relevant code to add another view...
}

-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController
   viewControllerAfterViewController:(UIViewController *)viewController
{
    // Relevant code to add another view...
}

-(UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
                  spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation

{
    // Setting a break point in here - never gets called

    if (UIInterfaceOrientationIsPortrait(orientation))
    {
        // Relevant code to create view...
        return UIPageViewControllerSpineLocationMin;
    }

    // Relevant code to create 2 views for side-by-side display and
    // set those views using self.pageViewController setViewControllers:

    return UIPageViewControllerSpineLocationMid
}

@end

これはすべて、前述したように完全に機能します。PageViewControllerのビューが表示されます。縦向きと横向きの両方でページを左右にスワイプすると、それぞれのページ番号が表示されます。ただし、横向きで2ページを並べて表示することはありません。spineLocationForInterfaceOrientationデリゲートメソッドにブレークポイントを設定しても、呼び出されることはありません。

これは、問題をデバッグ/解決する方法についてのアイデアを燃え尽きてしまったようなヘッドスクラッチャーです。UIPageViewControllerがデバイスの向きの変更に応答していないため、デリゲートメソッドを起動していないように動作します。ただし、ビューは正しくサイズ変更されます(ただし、その変更を処理するUIView自動サイズ変更マスクだけである可能性があります)。

このコード(および適切なXIbなど)だけで新しいプロジェクトを作成すると、完全に正常に機能します。だから私の実際のプロジェクトのどこかでこれを引き起こしている。どこを見続けるのかわからない。

いつものように、ありとあらゆる助けをいただければ幸いです。

サイドノート

タグ「uipageviewcontrollerspinelocation」を追加したかったのですが、長すぎてレピュテーションが不十分だったため追加できませんでした(1500が必要)。これは、Stackoverflowの特定のタグを回避するためのApple側の不正な策略だと思います...;-)

4

1 に答える 1

2

ついに問題を発見した。それはその症状の中で何か赤いニシンでしたが、まったく同じように関連していました。

メソッドにブレークポイントを設定するshouldAutorotateToInterfaceOrientation:ことは、UIViewControllerがローテーション通知を受け取っているかどうかを確認するための自然なテストでした。この問題に関するAppleの技術的なQ&Aに私を導いたのはそれではありませんでした:http://developer.apple.com/library/ios/#qa/qa1688/_index.html

その中で最も関連性のあるポイントは次のとおりです。

The view controller's UIView property is embedded inside UIWindow but alongside an additional view controller.

残念ながら、Appleは、従来のドキュメントスタイルでは、答えを提供せず、単に問題を確認するだけです。しかし、Stack Overflowに関する回答から、次の手がかりが得られました。

ナビゲーションコントローラースタック、サブビュー、またはモーダルコントローラーを使用せずにビューコントローラーの変更をアニメーション化しますか?

私のRootViewControllerはPageViewControllerをロードしていましたが、メインビューのサブビューとしてロードしていました。これは、親だけが変更に応答する2つのUIViewControllerがあることを意味しました。

PageViewControllerに方向の変更をリッスンさせる(したがって、関連するスパインデリゲートメソッドをトリガーする)ための解決策は、RootViewControllerからaddSubview:ビューコントローラーを削除して提示することでした。

[self presentViewController:pac animated:YES completion:NULL];

それが行われると、向きの変更が取得され、PageViewControllerがスパイン位置のデリゲートメソッドを起動していました。考慮すべき細部は1つだけです。ビューが横向きで起動された場合、縦向きに回転して横向きに戻るまで、ビューは縦向きのままでした。

これは、viewDidLoadを次のように編集することで簡単に調整できました。

PageContentViewController *page1 = [[PageContentViewController alloc] initWithNibName:@"PageContent" bundle:nil];

NSDictionary *pageViewOptions = nil;
NSMutableArray *pagesArray = [NSMutableArray array];

if (IS_IPAD && UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
{
    pageViewOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:UIPageViewControllerSpineLocationMid]
                                                  forKey:UIPageViewControllerOptionSpineLocationKey];

    PageContentViewController *page2 = [[PageContentViewController alloc] initWithNibName:@"PageContent" bundle:nil];

    [pagesArray addObject:page1];
    [pagesArray addObject:page2];
}
else
{
    [pagesArray addObject:page1];
}


self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
                                                          navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                                                                        options:pageViewOptions];
self.pageViewController.delegate = self;

[self.pageViewController setViewControllers:pagesArray
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:NO
                                 completion:NULL];

仕事は終わり、問題は解決しました。

于 2012-08-10T21:20:57.987 に答える