Iphone Xcode 4.5和iOS 6.x中的故事板定向支持?

Iphone Xcode 4.5和iOS 6.x中的故事板定向支持?,iphone,objective-c,ios6,storyboard,screen-orientation,Iphone,Objective C,Ios6,Storyboard,Screen Orientation,我已经创建了两个故事板,除了一个包含纵向视图和一个包含横向视图外,它们都是相同的 我不想使用自动调整大小遮罩,因为一些视图的布局在纵向和横向之间完全改变。过去我曾在代码中手动移动视图上的控件,但这次我采用了更简单的方法:) 我找到的最接近的解决方案来自“benyboariu”—— 下面是我正在使用的代码,它在iOS 5.x上运行良好,但在iOS 6.x上运行不好 - (void)updateLandscapeView { UIDeviceOrientation deviceOrientation

我已经创建了两个故事板,除了一个包含纵向视图和一个包含横向视图外,它们都是相同的

我不想使用自动调整大小遮罩,因为一些视图的布局在纵向和横向之间完全改变。过去我曾在代码中手动移动视图上的控件,但这次我采用了更简单的方法:)

我找到的最接近的解决方案来自“benyboariu”——

下面是我正在使用的代码,它在iOS 5.x上运行良好,但在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上调试时遇到的错误是:

由于未捕获的异常“UIViewControllerHierarchyInconsistency”而终止应用程序,原因:“一个视图一次最多只能与一个视图控制器关联!”!视图UIView:0x108276b0;帧=(0;568268);自动调整大小=RM+BM;动画={position=cabasicanition:0x10815c60;bounds=cabasicanition:0x1082a5e0;};layer=CALayer:0x10827710与RootViewController:0x10821f10关联。在将此视图与RootViewController:0x961a150关联之前,请清除此关联。”

我通常将视图控制器与NIB断开链接以修复此类错误,但无法使用情节提要来实现这一点


有人有什么想法吗?

将您的portait视图控制器更改为普通视图(将其从视图控制器中取出)。现在,您应该能够将其实例化为UIView并进行转换,而不必担心它与多个视图控制器关联。

好吧,在尝试了各种方法来解决这个问题之后,我提出了一个在iOS 5.x和6.x上工作的解决方案

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];
}
基本上,问题似乎是因为导航控制器,所以,不是这样做

self.view = landscape.view;

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

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

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];
}
if(UIDeviceOrientationIsLandscape(deviceOrientation)&&!self.appDelegate.IsShowingLandscape视图)
{
UIStoryboard*情节提要=[UIStoryboard情节提要,名称:@“主情节提要”捆绑包:[NSBundle mainBundle]];
SearchViewController*横向=[storyboard InstanceEviewController的标识符:@“SearchViewController横向”];
self.appDelegate.isShowingLandscapeView=是;
[UIView transitionWithView:横向。视图持续时间:0选项:UIViewAnimationOptionTransitionCross溶解| UIViewAnimationCurveEaseIn动画:^{
NSMutableArray*viewControllers=[NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
如果(视图控制器&&[viewControllers count]>0)
{
对于(整数索引=0;索引<[ViewController计数];索引++)
{
if([[[viewControllers objectAtIndex:index]view]标记]==1000)
{
RootViewController*root=[storyboard InstanceEviewController的标识符:@“RootViewController景观”];
[viewControllers replaceObjectAtIndex:index with object:root];
}
else if([[[viewControllers objectAtIndex:index]view]标记]==2000)
{
[viewControllers replaceObjectAtIndex:index with object:landscape];
}
}
[self.navigationController设置视图控制器:视图控制器];
}
}完成:空];
}
else if(UIDeviceOrientationSportRait(deviceOrientation)和&self.appDelegate.isShowingLandscapeView)
{
UIStoryboard*情节提要=[UIStoryboard情节提要,名称:@“MainstryBoard肖像”捆绑:[NSBundle mainBundle]];
SearchViewController*纵向=[storyboard InstanceEviewController标识符:@“SearchViewController”];
self.appDelegate.isShowingLandscapeView=否;
[UIView transitionWithView:纵向。视图持续时间:0选项:UIViewAnimationOptionTransitionCross溶解| UIViewAnimationCurveEaseIn动画:^{
NSMutableArray*viewControllers=[NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
如果(视图控制器&&[viewControllers count]>0)
{
对于(整数索引=0;索引<[ViewController计数];索引++)
{
if([[[viewControllers objectAtIndex:index]view]标记]==1000)
{
RootViewController*root=[storyboard实例化EVEWControllHitifier:@“RootViewController”];
[viewControllers replaceObjectAtIndex:index with object:root];
}
else if([[[viewControllers objectAtIndex:index]view]标记]==2000)
{
[viewControllers replaceObjectAtIndex:index with Object:portrait];
}
}
[self.navigationController设置视图控制器:视图控制器];
}
}完成:空];
}
我已经扩展了代码,展示了如何在导航控制器中的嵌套视图上进行此操作。如果您使用的是根视图控制器,显然不需要遍历所有视图控制器,只需替换索引0处的视图控制器即可


希望这对别人有帮助

我已经尝试从情节提要中的控制器中删除UIView,但看起来您只能在其中包含控制器,即您需要UIViewController而不是UIView,或者UITableViewController而不是UITableView,等等。您好,您将什么设置为1000,将什么设置为2000?