0

整天都在这个令人头疼的主要问题:-(

我有一个 UIPageViewController 的实例,它似乎没有触发委托方法:

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

我已经尝试了各种显示 UIPageViewController 的方法,并且已经确定了一种似乎可以正常工作的编程方法(而不是 Storyboard 方法),但有一个例外......当将 iPad 旋转为横向时,脊柱不会出现在中间点如预期。我根本无法找出为什么没有调用委托方法。

代码说明(例如简化)

考虑如下三个类:

  • 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 的视图已加载并采用全屏显示。

页面视图控制器

这是主力(仅显示相关方法)。我尝试了来自 Google 无限世界的各种示例,并直接从 Apple 文档中编写...

@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 的视图被显示出来。我可以纵向和横向左右滑动页面,并显示相应的页码。但是,我从来没有在横向视图中看到两个页面并排。在 spinLocationForInterfaceOrientation 委托方法中设置断点永远不会被调用。

这是一个令人头疼的问题,我已经耗尽了关于如何调试/解决问题的想法。它的行为几乎就像 UIPageViewController 没有响应设备的方向变化,因此没有触发委托方法。但是,视图会正确调整大小(但这可能只是处理该更改的 UIView 自动调整大小掩码)。

如果我只用这段代码(和适当的 XIb 等)创建一个全新的项目,它工作得非常好。所以我实际项目中的某个地方导致了这种情况。我不知道在哪里继续寻找。

像往常一样,非常感谢任何和所有帮助。

边注

我想添加标签“uipageviewcontrollerspinelocation”但不能,因为它太长而且我没有足够的声誉(需要 1500)。我认为这是 Apple 为避免 Stackoverflow 中的某些标签而采取的一种狡猾的策略...... ;-)

4

1 回答 1

2

终于发现问题了。它的症状有点像红鲱鱼,但同样相关。

在方法中放置一个断点shouldAutorotateToInterfaceOrientation:是一个自然的测试,以查看 UIViewController 是否甚至收到旋转通知。这并不是让我对这个问题进行苹果技术问答的原因: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,但我将其作为主视图的子视图。这意味着我有两个 UIViewController,只有父级会响应更改。

让 PageViewController 监听方向变化(从而触发相关的脊椎委托方法)的解决方案是addSubview:从 RootViewController 中移除并呈现视图控制器:

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

一旦完成,方向变化就会被拾取,并且 PageViewController 正在触发脊椎位置的委托方法。只有一个小细节需要考虑。如果视图以横向启动,则视图仍显示纵向,直到旋转为纵向并返回横向。

这很容易通过编辑 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 回答