Xcode 4.5和iOS 6.x中的故事板方向支持? [英] Storyboards Orientation Support in Xcode 4.5 and iOS 6.x ?

查看:105
本文介绍了Xcode 4.5和iOS 6.x中的故事板方向支持?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了两个相同的故事板,除了一个包含纵向视图和一个包含横向视图。

I've created two storyboards both identical except one contains portrait views and one contains landscape views.

我不想使用自动调整大小的掩码,因为布局一些观点在肖像和风景之间完全改变。我过去曾在代码中手动移动控件,但这次我更容易理解:)

I don't want to use autoresize masks because the layout of some of the views changes completely between portrait and landscape. I've manually moved controls on the view in code in the past but I was after an easier way this time :)

我找到的最接近的解决方案是来自' benyboariu' - xCode 4.2的故事板方向支持?

The closest solution I've found was from 'benyboariu' - Storyboards orientation support for xCode 4.2?

以下是我正在使用的代码,它在iOS 5.x上工作正常,但不适用于iOS 6.x.

Here's the code I'm using which works fine on iOS 5.x but not iOS 6.x.

- (void)updateLandscapeView
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;

if (deviceOrientation == UIDeviceOrientationUnknown)
{
    if ([[UIScreen mainScreen] bounds].size.height > [[UIScreen mainScreen] bounds].size.width)
    {
        deviceOrientation = UIDeviceOrientationPortrait;
        self.appDelegate.isShowingLandscapeView = NO;
    }
    else
    {
        deviceOrientation = UIDeviceOrientationLandscapeLeft;
        self.appDelegate.isShowingLandscapeView = YES;
    }
}

if (UIDeviceOrientationIsLandscape(deviceOrientation) && !self.appDelegate.isShowingLandscapeView)
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Landscape" bundle:[NSBundle mainBundle]];
    UIViewController * landscape = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController-Landscape"];
    self.appDelegate.isShowingLandscapeView = YES;
    [UIView transitionWithView:landscape.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
        self.view = landscape.view;
    } completion:NULL];
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) && self.appDelegate.isShowingLandscapeView)
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Portrait" bundle:[NSBundle mainBundle]];
    UIViewController * portrait = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController"];
    self.appDelegate.isShowingLandscapeView = NO;
    [UIView transitionWithView:portrait.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
        self.view = portrait.view;
    } completion:NULL];
}
}

我在iOS 6上调试时遇到的错误.x是:

The error I'm getting when debugging on iOS 6.x is:


由于未捕获的异常'UIViewControllerHierarchyInconsistency'而终止应用程序,原因:'视图最多只能与一个视图相关联控制器一次!查看UIView:0x108276b0; frame =(0 0; 568 268); autoresize = RM + BM;动画= {position = CABasicAnimation:0x10815c60; bounds = CABasicAnimation:0x1082a5e0; }; layer = CALayer:0x10827710与RootViewController:0x10821f10相关联。在将此视图与RootViewController关联之前清除此关联:0x961a150。'

Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'A view can only be associated with at most one view controller at a time! View UIView: 0x108276b0; frame = (0 0; 568 268); autoresize = RM+BM; animations = { position=CABasicAnimation: 0x10815c60; bounds=CABasicAnimation: 0x1082a5e0; }; layer = CALayer: 0x10827710 is associated with RootViewController: 0x10821f10. Clear this association before associating this view with RootViewController: 0x961a150.'

我通常将视图控制器与NIB取消链接以修复此类错误,但不能用故事板来解决这个问题。

I usually unlink the view controller from the NIBs to fix this kind of error but can't seam to do that with storyboards.

任何人都有任何想法?

推荐答案

好吧,在尝试各种方法尝试解决这个问题后,我想出了这个适用于iOS 5.x和6.x的解决方案。

Well, after trying all sorts of ways to try and fix this problem I've come up with this solution which works on iOS 5.x and 6.x.

基本上,问题似乎是因为导航控制器,所以,而不是做

Basically, the problem appears to be because of the navigation controller, so, instead of doing

self.view = landscape.view;

self.view = portrait.view;

您需要更换导航控制器堆栈中包含的所有视图控制器。

you need to replace all the view controllers contained in the navigation controllers stack.

我在下面的代码中所做的是创建导航控制器堆栈中所有视图控制器的NSMutableArray。然后循环每个视图控制器并获取视图标记以确定哪个视图需要替换。然后我只需用横向或纵向版本替换视图控制器,然后将导航控制器视图控制器数组设置为修改后的数组,从而替换所有视图控制器。

What I'm doing in the code below is to create an NSMutableArray of the all view controllers in the navigation controller stack. Then loop each view controller and get the view tag to determine which view needs replacing. Then I simply replace the view controller with the landscape or portrait version and then set the navigation controllers view controllers array to the modified array thus replacing all the view controllers.

if (UIDeviceOrientationIsLandscape(deviceOrientation) && !self.appDelegate.isShowingLandscapeView)
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Landscape" bundle:[NSBundle mainBundle]];
    SearchViewController * landscape = [storyboard instantiateViewControllerWithIdentifier:@"SearchViewController-Landscape"];
    self.appDelegate.isShowingLandscapeView = YES;
    [UIView transitionWithView:landscape.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
        NSMutableArray * viewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
        if (viewControllers && [viewControllers count] > 0)
        {
            for (NSUInteger index = 0; index < [viewControllers count]; index++)
            {
                if ([[[viewControllers objectAtIndex:index] view] tag] == 1000)
                {
                    RootViewController * root = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController-Landscape"];
                    [viewControllers replaceObjectAtIndex:index withObject:root];
                }
                else if ([[[viewControllers objectAtIndex:index] view] tag] == 2000)
                {
                    [viewControllers replaceObjectAtIndex:index withObject:landscape];
                }
            }

            [self.navigationController setViewControllers:viewControllers];
        }
    } completion:NULL];
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) && self.appDelegate.isShowingLandscapeView)
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Portrait" bundle:[NSBundle mainBundle]];
    SearchViewController * portrait = [storyboard instantiateViewControllerWithIdentifier:@"SearchViewController"];
    self.appDelegate.isShowingLandscapeView = NO;
    [UIView transitionWithView:portrait.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
        NSMutableArray * viewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
        if (viewControllers && [viewControllers count] > 0)
        {
            for (NSUInteger index = 0; index < [viewControllers count]; index++)
            {
                if ([[[viewControllers objectAtIndex:index] view] tag] == 1000)
                {
                    RootViewController * root = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController"];
                    [viewControllers replaceObjectAtIndex:index withObject:root];
                }
                else if ([[[viewControllers objectAtIndex:index] view] tag] == 2000)
                {
                    [viewControllers replaceObjectAtIndex:index withObject:portrait];
                }
            }

            [self.navigationController setViewControllers:viewControllers];
        }
    } completion:NULL];
}

我已经扩展了代码以展示如何在嵌套视图上运行在导航控制器中。如果你正在使用根视图控制器,你显然不需要遍历所有视图控制器,只需替换索引0处的视图控制器。

I've expanded the code to show how to get this working on nested views in the navigation controller. If you're working on the root view controller you obviously don't need to loop through all the view controllers, just replace the view controller at index 0.

希望这个帮助某人!

这篇关于Xcode 4.5和iOS 6.x中的故事板方向支持?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆