IOS 6强制设备朝向景观

时间:2012-09-28 13:22:01

标签: iphone objective-c orientation ios6

我给了一个应用程序说10个视图控制器。我使用导航控制器来加载/卸载它们。

除了一个以外的所有人都处于纵向模式。假设第7个VC处于景观状态。我需要它在加载时以横向呈现。

请建议在IOS 6中强制定位从纵向到横向的方法(在IOS 5中工作也很好。)

以下是我的表现之前 IOS 6:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    UIViewController *c = [[[UIViewController alloc]init] autorelease];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

呈现和解雇模态VC迫使应用程序检查其方向,因此shouldAutorotateToInterfaceOrientation被调用。

我在IOS 6中尝试过的内容:

- (BOOL)shouldAutorotate{
    return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationLandscapeLeft;
}

在加载时,控制器保持纵向。旋转设备后,方向改变就好了。但是我需要让控制器在加载时自动旋转到横向,因此用户必须旋转设备才能正确查看数据。

另一个问题:将设备旋转回纵向后,虽然我在supportedInterfaceOrientations中仅指定UIInterfaceOrientationMaskLandscape,但方向会转为纵向。为什么会这样?

此外,上述3种方法中的 NONE 正在被调用。

一些(有用的)数据:

  1. 在我的plist文件中,我指定了3个方向 - 所有方向都是颠倒的。
  2. 该项目是在Xcode 4.3 IOS 5中启动的。包括xib在内的所有类都是在Xcode 4.5 IOS 6之前创建的,现在我使用的是最后一个版本。
  3. 在plist文件中,状态栏设置为可见。
  4. 在xib文件中(我希望在横向上),状态栏为“无”,方向设置为横向。
  5. 感谢任何帮助。谢谢。

13 个答案:

答案 0 :(得分:43)

好的,伙计们,我会发布我的解决方案。

我有什么:

  1. 基于视图的应用程序,具有多个视图控制器。 (这是基于导航的,但由于方向问题,我不得不以视图为基础。)
  2. 所有视图控制器都是纵向的,除了一个 - landscapeLeft。
  3. 任务:

    1. 无论用户如何握住设备,我的一个视图控制器都必须自动旋转到横向。所有其他控制器必须是纵向的,并且在离开横向控制器后,应用程序必须强制旋转为纵向,无论用户如何握住设备。
    2. 这必须与IOS 6.x一样,与IOS 5.x一样
    3. 访问!

      更新删除了@IvanVučica建议的宏)

      在所有PORTRAIT视图控制器中覆盖如下自动旋转方法:

      - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
          return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
      }
      -(BOOL)shouldAutorotate {
          return YES;
      }
      - (NSUInteger)supportedInterfaceOrientations {
          return UIInterfaceOrientationMaskPortrait;
      }
      

      您可以看到2种方法:一种用于IOS 5,另一种用于IOS 6.

      您的LANDSCAPE视图控制器也是如此,但有一些添加和更改:

      - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
          [image_signature setImage:[self resizeImage:image_signature.image]];
          return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
      }
      -(BOOL)shouldAutorotate {
          return YES;
      }
      - (NSUInteger)supportedInterfaceOrientations {
          [image_signature setImage:[self resizeImage:image_signature.image]];
          return UIInterfaceOrientationMaskLandscapeLeft;
      }
      

      注意:要强制在 IOS 5 中进行自动旋转,您应该添加以下内容:

      - (void)viewDidLoad{
          [super viewDidLoad];
          if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
              [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];    
      }
      

      类似地,在您离开LANDSCAPE控制器后,无论您加载什么控制器,都应该再次强制IOS 5进行自动旋转,但现在您将使用UIDeviceOrientationPortrait,当您转到PORTRAIT控制器时:

      - (void)viewDidLoad{
              [super viewDidLoad];
              if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
                  [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];    
          }
      

      现在最后一件事(而且有点奇怪) - 您必须改变从控制器切换到另一个控制器的方式,具体取决于IOS:

      创建一个NSObject类“Schalter”(来自德语的“Switch”)。

      在Schalter.h中说:

      #import <Foundation/Foundation.h>
      
      @interface Schalter : NSObject
      + (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease;
      @end
      

      在Schalter.m中说:

      #import "Schalter.h"
      #import "AppDelegate.h"
      
      @implementation Schalter
      + (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{
      
          //adjust the frame of the new controller
          CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
          CGRect windowFrame = [[UIScreen mainScreen] bounds];
          CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
          VControllerToLoad.view.frame = firstViewFrame;
      
          //check version and go
          if (IOS_OLDER_THAN_6)
              [((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view];
          else
              [((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad];
      
          //kill the previous view controller
          [VControllerToRelease.view removeFromSuperview];
      }
      @end
      

      现在,这是您使用Schalter的方式(假设您从Warehouse控制器转到Products控制器):

      #import "Warehouse.h"
      #import "Products.h"
      
      @implementation Warehouse
      Products *instance_to_products;
      
      - (void)goToProducts{
          instance_to_products = [[Products alloc] init];
          [Schalter loadController:instance_to_products andRelease:self];
      }
      
      bla-bla-bla your methods
      
      @end
      

      当然你必须释放instance_to_products对象:

      - (void)dealloc{
           [instance_to_products release];
           [super dealloc];
      }
      

      嗯,就是这样。不要犹豫,我不在乎。这适用于那些寻求解决方案而非声誉的人。 干杯! Sava Mazare。

答案 1 :(得分:34)

这应该有效,它类似于iOS 6之前的版本,但有一个UINavigationController

UIViewController *portraitViewController = [[UIViewController alloc] init];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController];
[self.navigationController presentModalViewController:nc animated:NO];
[self.navigationController dismissModalViewControllerAnimated:NO];

我在推动下一个UIViewController之前打电话给我。即使当前UIViewController处于横向状态(也应该适用于纵向横向),它将强制下一个推送UIViewController以纵向模式显示。适用于iOS 4 + 5 + 6。

答案 2 :(得分:14)

我认为最好的解决方案是坚持官方的苹果文档。所以根据我使用以下方法,一切都在iOS 5和6上运行良好。 在我的VC中,我重写了以下方法:

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

iOS 6的方法,第一种方法返回支持的方向掩码(如其名称所示)

-(NSUInteger)supportedInterfaceOrientations{

    return UIInterfaceOrientationMaskPortrait;
}

第二个告诉你的VC哪个是VC显示时首选的界面方向。

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

只需更改您想要的方向的肖像;) 这个解决方案工作顺利,我不喜欢创建宏和其他东西的想法,这就是这个简单的解决方案。 希望这有帮助...

答案 3 :(得分:7)

我遇到了同样的问题,在我的应用程序中有27个视图,其中26个是纵向的,只有一个在所有方向(图像查看器:))。 在每个类上添加宏并替换导航不是我觉得舒服的解决方案......

所以,我想在我的应用程序中保留UINavigationController机制,而不是将其替换为其他代码。

怎么做:

@ 1在方法didFinishLaunchingWithOptions

中的应用程序委托中
if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
    // how the view was configured before IOS6
    [self.window addSubview: navigationController.view];
    [self.window makeKeyAndVisible];
}
else
{
    // this is the code that will start the interface to rotate once again
    [self.window setRootViewController: self.navigationController];
}

@ 2 因为navigationController只响应YES以进行自动旋转,所以我们需要添加一些限制: 扩展UINavicationController - &gt; YourNavigationController并将其链接到Interface Builder。

@ 3从导航控制器覆盖“anoying new methods”。

由于此类仅适用于此应用程序,因此可以承担责任 对于它的控制器并在他们的位置作出回应。

-(BOOL)shouldAutorotate {

    if ([self.viewControllers firstObject] == YourObject)
    {
         return YES;
    }
    return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
     if ([self.viewControllers firstObject] == YourObject)
    {
         return UIINterfaceOrientationMaskLandscape;
    }
    return UIInterfaceOrientationMaskPortrait;
}

我希望这会对你有所帮助,

答案 4 :(得分:3)

来自iOS 6 Release Notes

  

现在,iOS容器(例如UINavigationController)不会咨询他们的孩子以确定他们是否应该自动旋转。

您的rootViewController是否将shouldAutoRotate邮件中的ViewController邮件传递给您的VC?

答案 5 :(得分:2)

我使用与OP pre-ios6相同的方法(显示和解除模态VC)以横向模式显示单个视图控制器(所有其他视图控制器)。它在ios6中打破了风景VC以肖像显示。

要解决这个问题,我只是在横向VC中添加了preferredInterfaceOrientationForPresentation方法。似乎现在适用于os 5和os 6。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

- (BOOL)shouldAutorotate
{
return NO;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{    
return UIInterfaceOrientationLandscapeLeft;
}

答案 6 :(得分:2)

嘿伙计们在尝试了很多不同的可能解决方案后没有成功我提出以下解决方案希望它有所帮助!

我准备了一个食谱:)。

<强>问题: 您需要使用ios 6中的navigationcontroller更改viewcontrollers的方向。

<强>解决方案:

navigation suggested

第1步。一个初始UIviewcontroler触发模态segue到landscape和     肖像UInavigationControllers如图所示......

在UIViewController1中我们需要根据Appdelegate的全局变量进行2次segues动作....

-(void)viewDidAppear:(BOOL)animated{
    if([globalDelegate changeOrientation]==0){
        [self performSegueWithIdentifier:@"p" sender:self];
    }
    else{
        [self performSegueWithIdentifier:@"l" sender:self];
    }

}

我们还需要一种回到肖像&amp; |的方法景观....

- (IBAction)dimis:(id)sender {
    [globalDelegate setChangeOrientation:0];
    [self dismissViewControllerAnimated:NO completion:nil];
}

第2步。每个NavigationController上的第一个Pushed UiViewControllers都会启动     与...

-(NSUInteger)supportedInterfaceOrientations{
    return [self.navigationController supportedInterfaceOrientations];
}

-(BOOL)shouldAutorotate{
    return YES;
}

第3步。我们在UInavigationController的子类中覆盖supportedInterfaceOrientations方法....

你的customNavigationController中的

我们有.....

-(NSUInteger)supportedInterfaceOrientations{
    if([self.visibleViewController isKindOfClass:[ViewController2 class]]){

        return UIInterfaceOrientationMaskPortrait;
    }
    else{
        return UIInterfaceOrientationMaskLandscape;

    }

}

第4步。在故事板或代码中,将wantsFullScreenLayout标志设置为yes,同时设置为纵向和横向uinavigationcontrollers。

答案 7 :(得分:1)

尝试使用一个类别或被子类化的UINavigationController来指定所需的方向,然后转到所需的VC。阅读更多here

答案 8 :(得分:1)

作为替代方案,你可以使用块来做同样的事情:

UIViewController *viewController    = [[UIViewController alloc] init];
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:viewController animated:NO completion:^{
    [self dismissViewControllerAnimated:NO completion:nil];
}];

另外,在推送新视图之前调用它。

答案 9 :(得分:0)

转到Info.plist文件并进行更改enter image description here

答案 10 :(得分:0)

我遇到了同样的问题。如果要强制特定视图控制器以横向显示,请在将其推入导航堆栈之前立即执行。

UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
        if (currentOrientation == UIInterfaceOrientationPortrait ||
            currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
            [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];

        UIViewController *vc = [[UIViewController alloc] init];
        [self.navigationController pushViewController:vc animated:YES];
        [vc release];

答案 11 :(得分:0)

我通过继承UINavigationController并覆盖导航控制器的supportedInterfaceOrientations来解决它,如下所示:

- (NSUInteger)supportedInterfaceOrientations
{
     return [[self topViewController] supportedInterfaceOrientations];
}

所有控制器都实现了supportedInterfaceOrientations及其所需的方向。

答案 12 :(得分:-1)

我使用了以下解决方案。在具有与所有其他方向不同的方向的一个视图控制器中,我在 prepareForSegue 方法中添加了方向检查。如果目标视图控制器需要的界面方向与显示的当前视图控制器不同,则会发送一条消息,强制界面在隔离期间旋转。

#import <objc/message.h>

...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if(UIDeviceOrientationIsLandscape(self.interfaceOrientation))
    {
        UIInterfaceOrientation destinationOrientation;

        if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]])
        {
            UINavigationController *navController = (UINavigationController *)[segue destinationViewController];
            destinationOrientation = [navController.topViewController preferredInterfaceOrientationForPresentation];
        } else
        {
            destinationOrientation = [[segue destinationViewController] preferredInterfaceOrientationForPresentation];
        }

        if ( destinationOrientation == UIInterfaceOrientationPortrait )
        {
            if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
            {
                objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
            }
        }
    }
}