【问题标题】:How to change the device orientation programmatically in iOS 6 [duplicate]如何在 iOS 6 中以编程方式更改设备方向 [重复]
【发布时间】:2012-09-20 22:28:27
【问题描述】:

iOS 5 中,我们可以像这样以编程方式更改设备方向:

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];

但在 iOS 6 中,setOrientation 已弃用,如何在 iOS 6 中以编程方式更改设备方向?

【问题讨论】:

标签: ios objective-c uiinterfaceorientation


【解决方案1】:

你应该放置
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
在您的 AppDelegate didFinishLaunchingWithOptions 方法中。

然后,您可以在应用程序的任何位置获取当前方向:

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

并通过以下方式测试方向:

UIInterfaceOrientationIsPortrait(orientation) 
UIInterfaceOrientationIsLandscape(orientation)

像,像

if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
    // code for landscape orientation
     // OR
    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
     //  OR
    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];

}
else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
{
    // code for Portrait orientation
    //  OR
   [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortraitUpsideDown];
    //  OR
   [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}

【讨论】:

  • 太棒了!在 iOS6 之前不需要beginGeneratingDeviceOrientationNotifications,但现在你需要这条额外的行。非常感谢!
  • Receiver type 'UIDevice' for instance message does not declare a method with selector 'setOrientation:'
  • [[UIDevice currentDevice] setOrientation:]的作用是什么? 设备旋转时不会自动设置自己的方向吗?
  • 整个星期都在寻找解决方案,只有这段代码终于可以工作了!尤其是在具有相机预览和横向设备的 iPad 上,几乎不可能强制应用程序定向纵向。感谢您的回答!
  • 对我来说看起来很乱。 UIDevice 方向属性是只读的。即便如此,这是尝试使用 UIInterfaceOrientation 值设置 UIDevice 方向属性。
【解决方案2】:

这并没有回答如何更改设备方向,而是提供可能对您有所帮助的附加信息。

iOS 6 UI 界面方向 - shouldAutorotateToInterfaceOrientation:不工作

方法 shouldAutorotateToInterfaceOrientation: 在 iOS 6 中不受支持。它已弃用。以防万一如果你是一个新手,只是盯着可可工作,想知道为什么你的视图控制器在 iOS 6 中搞砸了而在 iOS 5 中完美,只要知道 shouldAutorotateToInterfaceOrientation: 不再受支持.即使它可能适用于 Xcode 4 到 4.3,但它不适用于 Xcode 4.5。

Apple 提供了一种新方法以更简洁的方式完成这件事。您改为使用 supportedInterfaceOrientations。它返回视图控制器支持的所有界面方向,一个界面方向值的掩码。

UIInterfaceOrientationMask 枚举:

这些常量是用于指定视图控制器支持的界面方向的掩码位。

typedef enum {
    UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
    UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
    UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
    UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
    UIInterfaceOrientationMaskLandscape =
        (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
    UIInterfaceOrientationMaskAll =
        (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
    UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
    UIInterfaceOrientationMaskAllButUpsideDown =
        (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
    UIInterfaceOrientationMaskLandscapeRight),
} UIInterfaceOrientationMask;

使用 shouldAutorotateToInterfaceOrientation: 方法:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return UIInterfaceOrientationIsLandscapeRight(toInterfaceOrientation);
}

使用supportedInterfaceOrientations方法:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

这些是 UIViewController 在 iOS6 中添加的关于方向的方法

  1. UIViewController preferredInterfaceOrientationForPresentation

  2. UIViewController shouldAutorotate

  3. UIViewController supportedInterfaceOrientations

在 iOS6 中向 UIApplication 添加了有关方向的方法

  1. UIApplication supportedInterfaceOrientationsForWindow:

  2. UIInterfaceOrientationMask

【讨论】:

  • 感谢您的回答,但我想以编程方式更改方向。如何使用 [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight] 更改方向,就像我们在 ios5 中所做的那样;
  • -1 这没有回答如何以编程方式更改设备方向的问题。
  • 这不是问题的答案。这更像是附加信息。
【解决方案3】:

Apple 在 中以编程方式更改设备方向非常困难(请注意)。

据我所知,完成您所要求的唯一方法是模拟设备方向的变化。

使用setTransform 旋转UIView 并重新应用它自己的框架可以获得所需的结果。

[YourView setTransform:CGAffineTransformMakeRotation(1.57)];
[YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];

当设备物理方向发生变化时,我们可以撤消转换。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [YourView setTransform:CGAffineTransformMakeRotation(0)];
    [YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];
}

【讨论】:

    【解决方案4】:

    试试这个:

    #import <objc/message.h>
    
    if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)){
            if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
            {
                objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
            }
        }
    

    【讨论】:

    • +1 表示此选项。可能会被 Apple 拒绝,但这是我的企业应用程序所需要的。
    • 完美运行!但是在它隐藏状态栏之后变得可见。
    • @JustinTanner 它确实在 iOS 7 中工作。不过你不需要#import
    • 它在IOS7.1的开发环境中工作但是,当我部署到App Store时,这在IPhone5s中不起作用任何猜测?
    • 这不是一个好的做法,也没有遵循 Apple 的指导方针 - 奇怪的是,您的应用没有因为使用私有库而被拒绝。我只是将它用于内部开发。
    【解决方案5】:

    试试这个...对我有用...

    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    UIView *view = [window.subviews objectAtIndex:0];
    [view removeFromSuperview]; [window addSubview:view];
    

    【讨论】:

      【解决方案6】:

      我发现强制设备改变方向的最简单方法是呈现一个新的视图控制器(使用presentViewController:animated:completion:),其中新的视图控制器指定了一个特定的首选方向(通过实现方法-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation)。

      当一个新的视图控制器出现时,正如预期的那样,方向将更改为新视图控制器首选的方向。因此,最简单的实现(最佳实践?)是将特定方向所需的所有功能嵌入到单独的视图控制器中,并根据需要呈现。系统会为你改变方向。

      显然,这可能并不适合所有用例,但幸运的是,同样的技巧适用于强制设备更改现有视图控制器的方向。

      诀窍是呈现一个具有您需要的特定首选方向的新视图控制器,然后立即隐藏它。当新的视图控制器出现时,这将导致方向临时改变。最好的部分是,当新的视图控制器被关闭时,原始(呈现)视图控制器的preferredInterfaceOrientationForPresentation 被再次查询,您可以在此处指定您想要的最终方向。

      这里要注意的一件重要事情是在原始视图控制器中临时禁用自动旋转(当从新呈现的然后关闭的视图控制器返回时),以便当用户将手机旋转到新方向时,它不会触发进一步的自动旋转。

      以下代码应该说明我的观点,我的示例强制旋转为纵向,如果您想要其他方向,只需相应更改即可。

      假设您有一个名为 Original 的原始视图控制器和一个名为 ForcePortrait 的临时视图控制器

      @interface Original : UIViewController
      {
          BOOL orientationToPortrait; //should set to NO by default
      }
      @end
      
      @implementation Original
      - (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation
      {
          if(orientationToPortrait)
          {
              //when we manually changed, show in Portrait
              return UIInterfaceOrientationPortrait;
          }
          else
          {
              //before manual orientation change, we allow any orientation
              return self.interfaceOrientation;
          }
      }
      
      -(BOOL) shouldAutorotate
      {
          //we should 'lock' the rotation once we manually change it
          return !orientationToPortrait;
      }
      
      -(void) changeOrientationToPortrait
      {
          //Sample method to change the orientation
          //when called, will show (and hide) the temporary view
          //Original.preferredInterfaceOrientationForPresentation will be called again after this method
      
          //flag this to ensure that we tell system we prefer Portrait, whenever it asked again
          orientationToPortrait = YES;
      
          //presenting the following VC will cause the orientation to temporary change
          //when the new VC is dismissed, system will ask what is our (Original) orientation preference again
          ForcePortrait* forcePortrait = [[ForcePortrait alloc] init];
          [self presentViewController:forcePortrait animated:NO completion:^{
              [forcePortrait dismissViewControllerAnimated:NO completion:nil];
          }];
      }
      
      
      @end
      
      @interface ForcePortrait : UIViewController
      @end
      
      @implementation ForcePortrait
      - (NSUInteger)supportedInterfaceOrientations
      {
          return UIInterfaceOrientationMaskPortrait;
      }
      
      - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
      {
          return UIInterfaceOrientationPortrait;
      }
      @end
      

      【讨论】:

      • 在这里为我工作!非常感谢!
      • 非常优雅的解决方案。对我来说在 iOS 7 上完美运行!
      • 一个很好的解决方案,除非我尝试从父视图控制器弹出到任何视图控制器,否则它会失败。
      • 有什么办法可以强制这个变化被动画化吗?我正在推动从图库(相机胶卷)中拉出的图像选择器控制器,并且在为新视图控制器的过渡设置动画之前,它会以非动画方式旋转状态栏而在我的视图中没有其他内容。
      【解决方案7】:
      - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
      {
          // Return YES for supported orientations
         return NO;
      }
      

      - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
      {
         return  interfaceOrientation == UIInterfaceOrientationPortrait
                 || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ;
      }
      

      【讨论】:

        【解决方案8】:
        if (self.interfaceOrientation != UIInterfaceOrientationLandscapeRight) {
        // http://stackoverflow.com/questions/181780/is-there-a-documented-way-to-set-the-iphone-orientation
        // http://openradar.appspot.com/radar?id=697
        // [[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight]; // Using the following code to get around apple's static analysis...
        [[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(id)UIInterfaceOrientationLandscapeRight];
        }
        

        【讨论】:

        • 在iOS7中不起作用,还会触发“PerformSelector可能会导致泄漏,因为它的选择器未知”警告。
        • 此解决方案不再有效。你说的对。但是,performSelector 上的(潜在)泄漏没什么。只要您分配一个有效的选择器,它就永远不会泄漏。
        【解决方案9】:

        @implementation UINavigationController(自动旋转)

         -(NSUInteger)supportedInterfaceOrientations
         {
           //make the check for iphone/ipad here
        
            if(IPHONE)
            {
              return UIInterfaceOrientationMaskPortrait;
            } 
            else
            {
              return UIInterfaceOrientationMaskLandscape;
            }
         }
        
         - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
         {
            return UIInterfaceOrientationPortrait;
         }
        
         - (BOOL)shouldAutorotate
         {
            return NO;
         }
        

        【讨论】:

          【解决方案10】:

          如果您想避免使用运行时库,请对 Bissy 的回答稍作修改:

          if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]))
          {
              if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
              {
                  int orientationPortrait = UIInterfaceOrientationPortrait;
                  NSMethodSignature *sig = [[UIDevice currentDevice] methodSignatureForSelector:@selector(setOrientation:)];
                  NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
                  [invo setTarget:[UIDevice currentDevice]];
                  [invo setSelector:@selector(setOrientation:)];
                  [invo setArgument:&orientationPortrait atIndex:2];
                  [invo invoke];
              }
          }
          

          【讨论】:

            【解决方案11】:

            这适用于 iOS7,强制自动旋转为纵向。

            //In your viewController.m
            #import <objc/message.h>
            
            // for autorotate viewController to portraid
            - (void)viewWillAppear:(BOOL)animated {
                UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation];
                switch (orientationStatusBar) {
                    case UIInterfaceOrientationPortrait:break;
                    case UIInterfaceOrientationLandscapeLeft:
                        objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait);
                        break;
                    case UIInterfaceOrientationLandscapeRight:
                        objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait);
                        break;
                    default:
                        break;
                }
            }
            
            // this permit autorotate
            - (BOOL) shouldAutorotate
            {
               // this lines permit rotate if viewController is not portrait
                UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation];
                if (orientationStatusBar != UIInterfaceOrientationPortrait) {
                    return YES;
                }
                //this line not permit rotate is the viewController is portrait
                return NO;
            }
            

            注意:我在我的应用程序中实现了此选项,但可能会被 Apple 拒绝(Austin 对 2012 年 10 月 Sergey K. 编辑的 6 的评论)。

            【讨论】:

              【解决方案12】:

              这是我的“五分钱”,在带有 ARC 的 iOS7 上测试过

              [[UIDevice currentDevice] setValue:
                                    [NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
                                          forKey:@"orientation"];
              

              这不会像 performSelector 那样产生“泄漏”警告。

              UIAlertView - 使用此代码,当您在 view(will/Did) 出现期间打开 UIAlertView 时,您会注意到除此视图之外的所有视图都是纵向的(苹果,真的吗?)我无法强制视图重新定向,但发现如果您在打开 UIAlertView 之前稍作延迟,则视图有时间更改方向。

              注意我将从 2014 年 9 月 12 日开始发布我的应用周,如果它通过或失败,我会更新帖子。

              【讨论】:

              • 它的作品,但 AlertViews 仍然作为纵向模式的设备出现
              • 天哪!那是真正的交易!非常感谢你,我变得非常绝望!
              • 苹果是否支持使用这种方法的应用程序?
              • 我很快就会知道的
              • 苹果拒绝这个吗?你发现了吗? @Lukasz'Severiaan'Grela
              【解决方案13】:

              这适用于 Xcode 6 和 5。

              - (BOOL)shouldAutorotate {return YES;}
              - (NSUInteger)supportedInterfaceOrientations {return (UIInterfaceOrientationMaskPortrait);}
              

              【讨论】:

                【解决方案14】:

                此代码适用于 iOS 8 或更高版本

                NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
                [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
                

                【讨论】:

                • 我写了相同的代码并且它工作正常但是如果我使用 [NSNumber numberWithInt: UIInterfaceOrientationLandscapeRight] 那么它也在同一个方向旋转(反时钟)。我想要从左到右旋转(顺时针方向旋转)。
                • 不应使用,这是苹果私有 API - 一旦他们将方向字符串更改为其他任何内容,您的应用就会崩溃。
                【解决方案15】:

                有趣的是,其他人在没有这样设置后没有遇到问题:

                + (void)setOrientation:(UIDeviceOrientation)orientation {
                    [UIDevice.currentDevice setValue:@(orientation) forKey:@"orientation"];
                    [UIViewController attemptRotationToDeviceOrientation];
                    [UIDevice.currentDevice setValue:@(UIDeviceOrientationUnknown) forKey:@"orientation"];
                }
                

                我的要求是能够强制方向,然后再次旋转到设备自然方向...有 UIDeviceOrientationDidChangeNotification 可以让您获得信息以女巫方向旋转设备,但实际上如果您不这样做,它将部分不起作用t 在 UIDevice 中更改方向后立即设置为未知,还有更多细节可以让它很酷但会离开它,因为它超出了这个简单问题的上下文。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-12-19
                  • 1970-01-01
                  • 2023-04-11
                  • 2014-01-26
                  • 1970-01-01
                  • 2020-12-31
                  相关资源
                  最近更新 更多