首页 文章

IOS 6强制设备朝向景观

提问于
浏览
57

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

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

Please suggest a way to force the orientation go from portrait to landscape in IOS 6 (也可以在IOS 5中工作) .

以下是我的表现 BEFORE 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 被调用 .

What I have have tried in IOS 6:

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

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

另一个问题:在将设备旋转回肖像后,方向转为纵向,尽管我在 supportedInterfaceOrientations 中仅指定了 UIInterfaceOrientationMaskLandscape . 为什么会这样?

此外,以上3种方法中的 NONE 被调用 .

Some (useful) data:

  • 在我的plist文件中,我指定了3个方向 - 所有方向都是颠倒的 .

  • 该项目是在Xcode 4.3 IOS 5中启动的 . 包括xib在内的所有类都是在Xcode 4.5 IOS 6之前创建的,现在我使用的是最后一个版本 .

  • 在plist文件中,状态栏设置为可见 .

  • 在xib文件中(我希望在横向上),状态栏为"None",方向设置为横向 .

任何帮助表示赞赏 . 谢谢 .

13 回答

  • 1

    作为替代方案,您可以使用块来执行相同的操作:

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

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

  • 14

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

  • 1

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

    是)我有的:

    • 基于视图的应用程序,具有多个视图控制器 . (这是基于导航的,但由于方向问题,我不得不将其视为基于视图) .

    • 所有视图控制器都是纵向的,除了一个 - landscapeLeft .

    任务:

    • 无论用户如何握住设备,我的一个视图控制器都必须自动旋转到横向 . 所有其他控制器必须是纵向的,并且在离开横向控制器后,应用程序必须强制旋转为纵向,无论用户如何握住设备 .

    • 这必须像IOS 6.x一样在IOS 5.x上运行

    走!

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

    In all your PORTRAIT view controllers override autorotation methods like this:

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

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

    The same for your LANDSCAPE view controller, with some additions and changes:

    - (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;
    }
    

    ATTENTION :强制在 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];    
        }
    

    Now the last thing (and it's a bit weird) - you have to change the way you switch from a controller to another, depending on the 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
    

    NOW, this is the way you use Schalter ( suppose you go from Warehouse controller to Products controller ) :

    #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];
    }
    

    Well, this is it. Don't hesitate to downvote, I don't care. This is for the ones who are looking for solutions, not for reputation. Cheers! Sava Mazare.

  • 0

    这应该工作,它类似于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 .

  • 7

    我认为最好的解决方案是坚持官方的苹果文档 . 所以根据我使用以下方法,一切都在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;
    }
    

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

  • 43

    我有同样的问题,在我的应用程序中有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 - > YourNavigationController并将其链接到Interface Builder中 .

    @ 3覆盖导航控制器的“新方法” .

    由于此类仅适用于此应用程序,因此它可以对其控制器负责并在其位置进行响应 .

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

    我希望这能帮到您,

  • 0

    来自iOS 6 Release Notes

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

    您的 rootViewController 将_2580000_消息传递到您的VC?

  • 2

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

    为了解决这个问题,我在landscape VC中添加了preferredInterfaceOrientationForPresentation方法 . 似乎现在可以在os 5和os 6上正常工作 .

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
    }
    
    - (BOOL)shouldAutorotate
    {
    return NO;
    }
    
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
    {    
    return UIInterfaceOrientationLandscapeLeft;
    }
    
  • 0

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

    我准备了一个食谱:) .

    Problem: 您需要在ios 6中使用navigationcontroller更改viewcontrollers的方向 .

    Solution:

    navigation suggested

    步骤1.一个初始UIviewcontroler触发模态segues到横向和纵向UInavigationControllers如图所示....

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

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

    我们还需要回到肖像和|景观....

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

    第2步 . 每个NavigationController的第一个Pushing 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.在storyboard或代码中,将wantsFullScreenLayout标志设置为yes,同时设置为纵向和横向uinavigationcontrollers .

  • -1

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

  • 2

    我有同样的问题 . 如果要强制特定视图控制器以横向显示,请在将其推入导航堆栈之前执行此操作 .

    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];
    
  • 34

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

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

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

  • 3

    我使用了以下解决方案 . 在具有与所有其他方向不同的方向的一个视图控制器中,我在 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 );
                }
            }
        }
    }
    

相关问题