最简单的方法来支持多个方向? 如何在应用程序处于横向模式时加载自定义的NIB?

我有一个应用程序,我想支持多个方向。 我有两个我想使用的.xib文件,myViewController.xib和myViewControllerLandscape.xib. myViewController.xib myViewControllerLandscape.xib. myViewController.xib存在于项目/资源中, myViewControllerLandscape.xib存在于根项目目录中。

我想要做的是为我的旋转使用单独的NIB (myViewControllerLandscape.xib) 。 我尝试在viewDidLoad l检测旋转viewDidLoad l ike this:

 if((self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)) { NSLog(@"Landscape detected!"); [self initWithNibName:@"myViewControllerLandscape" bundle:nil]; } 

但是我可以在gdb中看到,当应用程序以横向设备启动时,这不会被执行。 NSLog消息不会触发。 为什么是这样? 我做错了什么?

另外,如果我明确地将initWithNibName函数调用放在viewDidLoad方法中,那么该nib不会被加载,并且继续使用myViewController.xib文件。 我的电话有什么问题? 我应该指定一个包吗?

谢谢!

您必须加载一个视图,然后检查方向并根据需要加载另一个视图。 您在shouldAutorotateToInterfaceOrientation:检查方向shouldAutorotateToInterfaceOrientation:如果要旋转,则返回yes。

我使用导航控制器来pipe理转换。 如果我有纵向查看和设备旋转,我推动横向视图,然后在返回到肖像时popup横向视图。

编辑:

我在shouldAutorotateToInterfaceOrientation中为所有方向返回YES:但在应用程序启动时会调用此方法吗? 你在这个函数里面推你的视图吗?

方向常量不是您查询的全局variables,而是系统发送控制器的部分消息。 因此,在视图控制器加载之前,您无法轻松检测方向。 相反,你硬连线的应用程序开始在一个特定的方向(通常是肖像),然后立即旋转。 (请参阅移动Safari,它始终以纵向开始,然后旋转到横向。)

这是我用来replace我的肖像和风景的两种方法。

所有三个视图控制器都有这个方法:

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); } 

肖像有这样的:

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { if (toInterfaceOrientation==UIInterfaceOrientationLandscapeRight) { [self.nav pushViewController:rightLVC animated:NO]; } if (toInterfaceOrientation==UIInterfaceOrientationLandscapeLeft) { [self.nav pushViewController:leftLVC animated:NO]; } } 

每个景观控制器都有这个:

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { if (toInterfaceOrientation==UIInterfaceOrientationPortrait) { [self.nav popViewControllerAnimated:NO]; } 

该应用程序开始在肖像。 如果设备的方向是横向的,则推动适当的景观。 当设备旋转到肖像时,它会popup风景。 对用户来说,它看起来像重新组织自己不同的方向相同的观点。

我发现了一个独立于导航控制器的更好的方法。 现在,当embedded导航控制器时,我有这个工作,当没有embedded(虽然我现在不使用导航控制器,所以可能有一些我没有看到的错误 – 例如PUSH过渡animation可能会有趣的,或者什么的)

两个NIB,使用苹果的命名约定。 我怀疑,在iOS 6或7,苹果可能会将此添加为“function”。 我在我的应用程序中使用它,它完美的作品:

  1. 触发器将旋转,不应该旋转(等待,直到旋转animation即将开始)
  2. 对于横向/纵向文件使用Apple命名约定(如果您希望Apple自动加载横向版本,则Default.png为Default-landscape.png)
  3. 重新加载新的NIB
  4. 这将重置self.view – 这将自动更新显示
  5. 然后它调用viewDidLoad (如果你手动重载一个NIB,Apple不会为你调用这个)
 -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { if( UIInterfaceOrientationIsLandscape(toInterfaceOrientation) ) { [[NSBundle mainBundle] loadNibNamed: [NSString stringWithFormat:@"%@-landscape", NSStringFromClass([self class])] owner: self options: nil]; [self viewDidLoad]; } else { [[NSBundle mainBundle] loadNibNamed: [NSString stringWithFormat:@"%@", NSStringFromClass([self class])] owner: self options: nil]; [self viewDidLoad]; } } 

真的很喜欢亚当的答案 – 我稍微修改它允许在纵向或横向的初始加载笔尖

 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if( !nibNameOrNil ) nibNameOrNil = [self nibNameRotated:[[UIApplication sharedApplication] statusBarOrientation]]; self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; return self; } - (NSString*) nibNameRotated:(UIInterfaceOrientation)orientation { if( UIInterfaceOrientationIsLandscape(orientation)) return [NSString stringWithFormat:@"%@-landscape", NSStringFromClass([self class])]; return [NSString stringWithFormat:@"%@", NSStringFromClass([self class])]; } -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { NSString *nibname = [self nibNameRotated:toInterfaceOrientation]; [[NSBundle mainBundle] loadNibNamed:nibname owner:self options:nil]; [self viewDidLoad]; } 

我喜欢TechZen接受的答案,但正如Adam的评论中指出的那样,当你旋转到横向时,它将纵向视图控制器留在导航堆栈中。 这意味着在横向导航栏中点击后退button将使用户进入纵向视图。 同事,我正在尝试手动删除导航堆栈中的额外项目的方法。 它似乎工作,但我还没有经验,所以我没有任何承诺。 这里是示例代码:

从肖像走向景观:

 [[self navigationController] pushViewController:landscapeViewController animated:NO]; [self removeFromNavigationStack:[MyPortraitViewController class]]; 

回到肖像:

 [[self navigationController] pushViewController:portraitViewController animated:NO]; [self removeFromNavigationStack:[MyLandscapeViewController class]]; 

如果您不使用animation:否,您可能会收到有关导航状态的警告。

帮手:

 - (void)removeFromNavigationStack:(Class)oldClass { UINavigationController *nav = [self navigationController]; NSMutableArray *newStack = [NSMutableArray array]; for (UIViewController *vc in nav.viewControllers) { if (![vc isMemberOfClass:[oldClass class]]) { [newStack addObject: vc]; } [nav setViewControllers:newStack animated:NO]; } 

多一个select, TPMultiLayoutViewController 。