Xcode 4.5 和 iOS 6.x 中的故事板方向支持?
Posted
技术标签:
【中文标题】Xcode 4.5 和 iOS 6.x 中的故事板方向支持?【英文标题】:Storyboards Orientation Support in Xcode 4.5 and iOS 6.x ? 【发布时间】:2012-12-11 14:53:39 【问题描述】:我创建了两个相同的故事板,除了一个包含纵向视图和一个包含横向视图。
我不想使用自动调整大小的蒙版,因为某些视图的布局在纵向和横向之间完全不同。过去我在代码中手动移动了视图上的控件,但这次我采用了一种更简单的方法:)
我找到的最接近的解决方案来自 'benyboariu' - Storyboards orientation support for xCode 4.2?
这是我正在使用的代码,它在 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 0; 568 268);自动调整大小 = RM+BM;动画=位置=CABasicAnimation:0x10815c60;边界=CABasicAnimation:0x1082a5e0; ; layer = CALayer: 0x10827710 与 RootViewController: 0x10821f10 相关联。在将此视图与 RootViewController 关联之前清除此关联:0x961a150。'
我通常将视图控制器与 NIB 断开链接以修复此类错误,但无法通过情节提要进行缝合。
有人有什么想法吗?
【问题讨论】:
【参考方案1】:将您的肖像视图控制器更改为普通视图(将其从视图控制器中取出)。现在您应该能够将它实例化为 UIView 并进行转换,而不必担心它与多个视图控制器相关联。
【讨论】:
我已经尝试从情节提要中的控制器中删除 UIView,但看起来您只能在其中拥有控制器,即您需要 UIViewController 而不是 UIView,或者 UITableViewController 而不是 UITableView,等【参考方案2】:好吧,在尝试了各种方法来尝试解决这个问题之后,我想出了这个适用于 iOS 5.x 和 6.x 的解决方案。
基本上,问题似乎是因为导航控制器,所以,而不是这样做
self.view = landscape.view;
或
self.view = portrait.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];
我已经扩展了代码以展示如何在导航控制器中的嵌套视图上使用它。如果您正在处理根视图控制器,您显然不需要遍历所有视图控制器,只需替换索引 0 处的视图控制器。
希望这对某人有所帮助!
【讨论】:
嗨,你设置为 1000 和 2000 是多少?以上是关于Xcode 4.5 和 iOS 6.x 中的故事板方向支持?的主要内容,如果未能解决你的问题,请参考以下文章
对 iOS 5.0 和 iOS 6.0 使用 XCode 4.5 的困惑
带有 iOS 7 的 Xcode 5 中的 NSInternalInconsistencyException:“故事板:容器视图中有意外的子视图。”