iOS 6:将视图控制器推入导航控制器堆栈时如何强制更改方向

4
我认为这个问题可能已经被问了无数次,但我仍然找不到答案。
这是我的层次结构:UINavigationController -> UIViewController 1 ->(push)-> UIViewController 2
UINavigationController:支持所有可能的方向 UIViewController 1:只支持竖屏 UIViewController 2:只支持横屏
如何将UIViewController 1锁定为仅支持竖屏,同时将UIViewController 2锁定为仅支持横屏?这是否可能?到目前为止,我看到的是UIViewController 2总是采用UIViewController 1的方向。
请注意,这仅适用于iOS 6。
谢谢!

试试这个,它会对你有用的:https://dev59.com/b2cs5IYBdhLWcg3w3HoG - yen
你找不到答案是因为这是无法实现的。尽管下面有很多答案,但你所要求的在iOS 6中根本不被支持。iOS 6允许响应设备旋转,但不支持强制旋转。在iOS 6中强制旋转的唯一方法是使用一个已呈现的视图控制器,而不是推入导航控制器堆栈的视图控制器。 - matt
然而,您可以以这样的方式构建一个呈现的视图控制器,使其看起来就像是同一导航界面的一部分。由于呈现的视图控制器在呈现和解除呈现时都可以强制旋转,因此这有效地解决了问题。例如,请参见我的答案:http://stackoverflow.com/a/4103137/341994 - matt
1
我制作了一个视频展示我的意思:http://youtu.be/O76d6FhPXlE。正如你所看到的,它有点像是我在将第二个视图推入导航控制器并强制旋转。但实际上有*两个*导航控制器;第二个是以模态方式呈现的,因此当它出现和解除时,我可以强制旋转。 - matt
感谢@matt。这完全解释了为什么我迄今尝试的所有方法都不起作用。特别感谢您详细解释甚至创建一个短视频。非常有帮助!!由于我无法将您的评论标记为已接受的答案,因此我只是点赞了您的评论。 - ymotov
3个回答

13

我也遇到了同样的问题。我发现 shouldAutorotate 函数并没有每次都被调用,所以我通过编程方式改变了方向。

首先导入这个:

#import <objc/message.h>

然后

-(void)viewDidAppear:(BOOL)animated
{

     if(UIDeviceOrientationIsPortrait(self.interfaceOrientation)){
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
        {
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationLandscapeLeft );


        }
    }

}

希望这能帮助到你。


setOrientation是一个未记录的方法,使用它可能会导致您的应用被AppStore开除。请自行承担风险。 - Martin
不,这不是真的。我也在我的应用程序中使用了这种方法,并且已经在应用商店上线了。 - Sumit Mundra
苹果曾经有一个公共的读写属性用于方向控制,但现在已将其改为只读。上述方法是一种危险的技巧,可以让你访问他们的私有设置器。这很可能会导致你的应用被拒绝。虽然在你的情况下没有出现问题,但使用此方法需自担风险。 - TheCodingArt
终于!谢谢!清晰简单! - skywinder
这会导致界面按您想要的方式旋转,但不要忘记在此之后立即切换回来,否则设备会认为它处于错误的方向。可以通过在第二行中添加以下内容来解决:objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), _yourRealInterfaceOrientation ); - user726522

9
添加一个新的Objective-C类(UINavigationController的子类),并将以下代码添加到.m文件中。
-(NSUInteger)supportedInterfaceOrientations
 {
     NSLog(@"supportedInterfaceOrientations = %d ", [self.topViewController         supportedInterfaceOrientations]);

     return [self.topViewController supportedInterfaceOrientations];
 }

-(BOOL)shouldAutorotate
  {
     return self.topViewController.shouldAutorotate;
  }

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  {
    // You do not need this method if you are not supporting earlier iOS Versions

    return [self.topViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
  }

在添加新类之后,转到您的ViewController类并进行以下更改。
- (BOOL)shouldAutorotate  // iOS 6 autorotation fix
  {
    return YES;
  }
- (NSUInteger)supportedInterfaceOrientations // iOS 6 autorotation fix
  {
      return UIInterfaceOrientationMaskAll;
  }

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation // iOS 6 autorotation fix
  {
      return UIInterfaceOrientationPortrait;
  }
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
  {
      return YES;
  }

enter image description here

在 shouldAutorotate 方法和 shouldAutorotateToInterfaceOrientation 方法中,如果您希望 ViewController 支持多种方向,请返回 YES,否则返回 NO。同时,在 shouldAutorotateToInterfaceOrientation 方法中,指定您希望该特定 ViewController 使用的方向。对于所有的视图控制器都要重复这个步骤。

这样做的原因:

1:虽然您可以更改任何 viewController 的 preferredInterfaceOrientationForPresentation 属性以指定特定的方向,但由于您正在使用 UINavigationController,您还需要覆盖其 supportedInterfaceOrientations 属性。

2:为了覆盖 UINavigationController 的 supportedInterfaceOrientations 属性,我们创建了 UINavigationController 的子类并修改与 UINavigation 方向相关的方法。

希望这能帮助您!


将其作为AppDelegate的类别附加更干净、更容易,而不是为此创建一个新类,但两种方法都可以工作。 - BootMaker
+1 对这个好答案。这是一种适合旋转的方式。 - Nishant Tyagi
太棒了!工作得很好,解决方案也很不错。 - adsurbum
3
嗯,不行。它无法正常工作。我不知道昨天检查时是如何的,但点击返回按钮后父视图控制器获取了儿子的方向。 - adsurbum

1
使应用程序仅支持竖屏模式,并将以下行添加到UIViewController 2的initWithNibName中。
self.view.transform = CGAffineTransformMakeRotation(M_PI/2);

这不是方向的改变。 - NightFury

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接