iOS6 自动旋转 - UIPageViewController

Posted

技术标签:

【中文标题】iOS6 自动旋转 - UIPageViewController【英文标题】:iOS6 autorotation - UIPageViewController 【发布时间】:2012-09-24 16:00:51 【问题描述】:

我的 UI 结构:

UINavigationController
--UIViewController(first)
 |
 |Modal 
 |
 V 
UINavigationController (subclass)
--UIViewController (contains UIPageViewController)

对于ios6新的自动旋转,我创建了一个UINavigationController的子类并添加了:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    return UIInterfaceOrientationIsPortrait(interfaceOrientation);


- (BOOL)shouldAutorotate

    return YES;


- (NSUInteger)supportedInterfaceOrientations

    return UIInterfaceOrientationMaskPortrait;

只想保持方向是纵向的。

然后我像这样初始化 UIPageViewController:

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

    PageDataViewController *startingViewController = [self viewControllerAtIndex:start storyboard:self.storyboard];

    NSArray *viewControllers = [NSArray arrayWithObject:startingViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];

    self.pageViewController.dataSource = self;

    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];

    // Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
    CGRect pageViewRect = self.view.bounds;
    self.pageViewController.view.frame = pageViewRect;

    [self.pageViewController didMoveToParentViewController:self];

然后我执行模态转场, 如果第一个 UIViewController 是纵向的,则 pageViewController 有效, 但是如果第一个 UIViewController 是横向的,我总是会遇到异常:

* -[UIPageViewController willAnimateRotationToInterfaceOrientation:duration:] 中的断言失败, /SourceCache/UIKit_Sim/UIKit-2372/UIPageViewController.m:945 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“没有视图控制器” ** 第一次抛出调用堆栈:(0x2a5e012 0x19bae7e 0x2a5de78 0x1450f35 0xd75974 0x9f12b4 0x9f13ea 0x9e4c32 0x9f1372 0x9f13ea 0x9e4c32 0x9f1372 0x9f1751 0x93a1a6 0xbee5f9 0x9ec4f3 0x9ec777 0x9ec7b7 0xd57fe2 0xd49ad9 0xd49b54 0x9b1899 0x9b1b3d 0x13b8e83 0x2a1d376 0x2a1ce06 0x2a04a82 0x2a03f44 0x2a03e1b 0x2c967e3 0x2c96668 0x90265c 0xea7d 0x2685 0x1) libc++abi.dylib: 终止调用抛出一个 异常

【问题讨论】:

【参考方案1】:

其实还有另一种解决方案。

旋转只是调用了rootViewController的willAnimateRotationToInterfaceOrientation方法,你必须实现它的方法。

@interface UIPageViewController (Rotation)
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
@end

//实现文件

#import "UIPageViewController+Rotation.h"

@implementation UIPageViewController(Rotation)
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
@end

【讨论】:

【参考方案2】:

在有关“supportedInterfaceOrientations”的文档中写道:

当用户更改设备方向时,系统会在根视图控制器或填充窗口的最顶部呈现的视图控制器上调用此方法

您是否尝试将主窗口的 rootViewController 设置为您当前的 NavigationController 类?

就像在 AppDelegate 中一样:

self.window.rootViewController = nvc;

当你的 navigationController 发生变化时,再次设置 rootViewController...

【讨论】:

【参考方案3】:

我已经“修复”了这个问题,通过再次在viewWillAppear: 中将视图控制器设置为UIPageViewController,因为当调用此方法时,页面视图控制器的脊椎位置是正确的,并且基于此信息我设置了一个,或者两个页面(视图控制器)

- (void)viewWillAppear:(BOOL)animated
   
    [super viewWillAppear:animated];

    if(self.pageViewController.spineLocation == UIPageViewControllerSpineLocationMid)
    
        BookPageViewController *currentViewController = self.pageViewController.viewControllers[0];
        NSArray *viewControllers = nil;

        NSUInteger indexOfCurrentViewController = [self.modelController indexOfViewController:currentViewController];
        if (indexOfCurrentViewController == 0 || indexOfCurrentViewController % 2 == 0) 
            UIViewController *nextViewController = [self.modelController pageViewController:self.pageViewController viewControllerAfterViewController:currentViewController];
            viewControllers = @[currentViewController, nextViewController];
         else 
            UIViewController *previousViewController = [self.modelController pageViewController:self.pageViewController viewControllerBeforeViewController:currentViewController];
            viewControllers = @[previousViewController, currentViewController];
        
        [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward | UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
    

    if(self.pageViewController.spineLocation == UIPageViewControllerSpineLocationMin)
    
        [self.pageViewController setViewControllers:[NSArray arrayWithObject:[self.pageViewController.viewControllers objectAtIndex:0]] direction:UIPageViewControllerNavigationDirectionForward | UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];
    

并设置UIPageViewController委托方法如下

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

    BookPageViewController *currentViewController = self.pageViewController.viewControllers[0];

    if(UIInterfaceOrientationIsPortrait(orientation))
    
        [self.pageViewController setViewControllers:[NSArray arrayWithObject:currentViewController] direction:UIPageViewControllerNavigationDirectionForward | UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];

        pageViewController.doubleSided = NO;

        return UIPageViewControllerSpineLocationMin;
    

    if(UIInterfaceOrientationIsLandscape(orientation))
    
        NSArray *viewControllers = nil;

        NSUInteger indexOfCurrentViewController = [self.modelController indexOfViewController:currentViewController];
        if (indexOfCurrentViewController == 0 || indexOfCurrentViewController % 2 == 0) 
            UIViewController *nextViewController = [self.modelController pageViewController:self.pageViewController viewControllerAfterViewController:currentViewController];
            viewControllers = @[currentViewController, nextViewController];
         else 
            UIViewController *previousViewController = [self.modelController pageViewController:self.pageViewController viewControllerBeforeViewController:currentViewController];
            viewControllers = @[previousViewController, currentViewController];
        
        [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward | UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil];

        return UIPageViewControllerSpineLocationMid;
    

    return UIPageViewControllerSpineLocationMin;

【讨论】:

【参考方案4】:

我已经“修复”了这个问题,通过在 viewWillAppear 中将视图控制器设置为 UIPageViewController: 再次,因为当调用此方法时,页面视图控制器的脊椎位置是正确的,并且基于此信息我设置了一页或两页(视图控制器)

【讨论】:

以上是关于iOS6 自动旋转 - UIPageViewController的主要内容,如果未能解决你的问题,请参考以下文章

IOS 6 - 自动旋转 MPMovieplayer

ECSlidingViewController,禁用旋转iOS6

ios4+的UITabBar自动旋转

用于 youtube 嵌入式视频的 iOS 6.0+ 自动旋转

IOS6 使用自动布局的约束

UITabBarController 中的 UINavigationController 在 iOS 6 中不会旋转