【问题标题】:iOS: Device orientation on loadiOS:加载时的设备方向
【发布时间】:2011-05-04 18:16:53
【问题描述】:

似乎当我的应用加载时,它不知道当前的方向:

UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationPortrait) {
    NSLog(@"portrait");// only works after a rotation, not on loading app
}

旋转设备后,我得到了正确的方向,但是当我加载应用程序时,在不改变方向的情况下,使用[[UIDevice currentDevice] orientation] 似乎不知道当前方向。

当我第一次加载我的应用程序时,还有其他方法可以检查吗?

【问题讨论】:

标签: iphone ios uiinterfaceorientation uidevice


【解决方案1】:

编辑:我误读了您的问题。这将允许您以特定方向启动应用程序。刚刚意识到您正在尝试确定启动时的方向。

UIApplication上有一种检查状态栏方向的方法:

[[UIApplication sharedApplication] statusBarOrientation];

原答案

尝试在 plist 文件中设置应用程序接受的设备方向:

<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
</array>

这表明您的应用程序支持纵向(底部的主页按钮)、横向左侧和横向右侧。

然后,在您的 UIViewControllers 中,您将需要覆盖 shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) 方法以在应用旋转时返回 YES:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

     return interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight;
}

如果设备处于您支持的方向之一,这将告诉 UIViewController 自动旋转。如果您也想支持倒置方向(顶部带有主页按钮的肖像),请将其添加到您的 plist 中,然后在此方法中返回 YES。

让我们知道结果如何。

【讨论】:

  • 是的,检查 statusbarOrientation 是诀窍!
  • 请注意,邮件名为 statusBarOrientation(不是带有小写“b”的 statusbarOrientation)- 已提交编辑以供审核。
  • 不适合我我每次都得到肖像。我正在为 Ipad 尝试它并在模拟器上进行测试。它取决于硬件。它可以在设备上工作吗?
  • 这不起作用:如果父视图尚未旋转到当前方向,则设备可以处于与状态栏不同的方向。
  • shouldAutorotateToInterfaceOrientation 将根据 root vc 是否为导航控制器而有所不同。
【解决方案2】:

我认为这会奏效:

 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];UIInterfaceOrientation orientation = [UIDevice currentDevice].orientation;

根据 UIDevice 参考:
引用:
"除非已通过调用 beginGeneratingDeviceOrientationNotifications 启用方向通知,否则此属性的值始终返回 0"
我最初假设此属性始终包含当前方向,但显然并非如此。我猜想在通常访问方向属性的其他情况下,在幕后为我们处理打开通知,所以这并不明显需要在应用程序委托中手动完成

【讨论】:

  • 这似乎不起作用,我最终使用了 [UIApplication sharedApplication].statusBarOrientation 。
【解决方案3】:

对于那些寻找 Swift 3 或 4 答案的人。只需将该代码添加到 viewDidLoad() 块内。

let orientation = UIApplication.shared.statusBarOrientation
if orientation == .portrait {
      // portrait   
} else if orientation == .landscapeRight || orientation == .landscapeLeft{
      // landscape     
}

IOS 13 和 Swift 5.x 的折旧警报更新使用下面的代码块。

 if #available(iOS 13.0, *) {
        let orientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
        if orientation == .portrait {
                     // portrait

               } else if orientation == .landscapeRight || orientation == .landscapeLeft{
                     // landscape
               }
    } else {
        // Fallback on earlier versions
        let orientation = UIApplication.shared.statusBarOrientation
        if orientation == .portrait {
                            // portrait

    } else if orientation == .landscapeRight || orientation == .landscapeLeft{
                               // landscape
    }
    }

【讨论】:

  • 我确实收到了一条消息,说 statusBarOrientation 已被弃用。也许您可以使用新值更新您的答案?
【解决方案4】:

还没有人提到的一件事是您将UIDeviceOrientation 类型存储在UIInterfaceOrientation 变量中。它们是不同的,不应被视为平等。请注意UIDeviceOrientationLeft 等于UIInterfaceOrientationRight(因为与设备相比,界面旋转的方向相反)。

【讨论】:

  • 是的,设备方向包括面朝下和面朝上。 iOS 6 是修复设备/界面方向问题的垫脚石。 iOS
【解决方案5】:

您可以通过在里面插入以下通知来做到这一点

-(void)viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkRotation:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];

然后将以下方法放入您的类中

-(void)checkRotation:(NSNotification*)notification
{
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
    {
         //Do your textField animation here
    }
}

上述方法将检查 ipad 或 iPhone 状态栏的方向,并根据它制作所需方向的动画。

【讨论】:

    【解决方案6】:

    加载时设备方向可以是.Unknown.FaceUp。为了确定是纵向还是横向,我使用statusBarOrientation 作为备份,如下所示:

        var portraitOrientation = UIDevice.currentDevice().orientation == .Portrait
    
        if UIDevice.currentDevice().orientation == .Unknown || UIDevice.currentDevice().orientation == .FaceUp {
            portraitOrientation = UIApplication.sharedApplication().statusBarOrientation == .Portrait
        }
    

    这样我可以确保portraitOrientation 总是告诉我设备是否处于纵向模式,否则它将处于横向模式。即使是第一次加载应用程序。

    【讨论】:

      【解决方案7】:

      为了从状态栏获取方向,在 plist 文件中启用所有方向也很重要。

      【讨论】:

        【解决方案8】:

        Swift 3 基于 @Marjin 的代码。

        var portraitOrientation = UIDevice.current.orientation == .portrait
        
        if UIDevice.current.orientation == .unknown || UIDevice.current.orientation == .faceUp {
             portraitOrientation = UIApplication.shared.statusBarOrientation == .portrait
        }
        
        if(portraitOrientation)
        {
             // Portrait
        }
        else
        {
        
        }
        

        【讨论】:

          【解决方案9】:

          尝试使用加速度计获取其读数,UIAccelerometer,获取 sharedAccelerometer,设置其委托,获取读数,从那里找出方向。

          【讨论】:

          • 是的,但较旧的 iPod touch 没有加速度计,所以这在我的情况下不起作用。
          • 实际上,即使是第一个 ipod touch 也有加速度计
          【解决方案10】:

          尝试了所有,没有好的结果。所以我在 ipad 上所做的就是将所有工作留给 splitViewController 方法来使 barButton 无效:

          肖像:

          - (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController: (UIPopoverController *)pc { NSlog(@"portrait");}
          

          横向:

          - (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem{ NSlog(@"landscape");}
          

          这总是在加载时工作。

          【讨论】:

            【解决方案11】:

            问题是[UIDevice currentDevice]orientation] 有时会错误地报告设备的方向。

            改为使用[[UIApplication sharedApplication]statusBarOrientation],它是UIInterfaceOrientation,所以要检查它,您需要使用UIInterfaceOrientationIsLandscape(orientation)

            希望这会有所帮助。

            【讨论】:

            • 什么情况下设备的方向报错?你能举个例子吗?
            【解决方案12】:

            我仍然在 iphone 4 上使用这个工作代码 sn-p:

            -(void)deviceOrientationDidChange:(NSNotification *)notification{
            
            //Obtaining the current device orientation
            UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];    
            
            int value = 0;
            
            if(orientation == UIDeviceOrientationPortrait)
            {
                value = 0;
            
            }else if(orientation == UIDeviceOrientationLandscapeLeft)
            {
                value = 90;
            
            }else if(orientation == UIDeviceOrientationLandscapeRight)
            {
            
                value = -90;
            
            }
            
            CGAffineTransform cgCTM = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(value));
            [photoImageView setTransform:cgCTM];
            

            }

            【讨论】:

              【解决方案13】:

              这才是真正的答案。当应用程序启动时,它的方向是未知的。它使用 shouldAutorotateToInterfaceOrientation 和 supportedInterfaceOrientations 来决定选择哪个方向。

              观看我在 iPhone 5.0 模拟器中启动示例应用程序并使用以下代码和“支持的界面方向”以及所有 4 种可能的方向旋转它:

              20:44:08.218 RotationTestApp Supported orientation: Portrait
              20:44:08.222 RotationTestApp Supported orientation: Portrait (upside-down)
              20:44:08.225 RotationTestApp Supported orientation: Landscape (home button on the right)
              20:44:08.225 RotationTestApp Supported orientation: Landscape (home button on the left)
              20:44:08.226 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (current device orientation: UIDeviceOrientationUnknown, interface orientation wants: UIInterfaceOrientationPortrait)
              20:44:08.237 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (current device orientation: UIDeviceOrientationUnknown, interface orientation wants: UIInterfaceOrientationPortrait)
              20:44:08.239 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (current device orientation: UIDeviceOrientationUnknown, interface orientation wants: UIInterfaceOrientationPortrait)
              20:44:08.240 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (current device orientation: UIDeviceOrientationUnknown, interface orientation wants: UIInterfaceOrientationPortrait)
              20:44:09.817 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationLandscapeLeft)
              20:44:09.833 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationLandscapeLeft)
              20:44:11.030 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationPortraitUpsideDown)
              20:44:11.040 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationPortraitUpsideDown)
              20:44:12.599 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationLandscapeRight)
              20:44:12.609 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationLandscapeRight)
              20:44:13.301 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationPortraitUpsideDown)
              

              我见过很多代码 sn-ps,但它们都不能正常工作(iPad 和 iPhone,iOS 5.0+)。

              不要在try-this-try-that中摸索,而是将以下内容放在您的根vc中:

              #define ToNSString_BEGIN(T) \
              NSString* T##ToNSString(T valueParameter) { \
              switch (valueParameter) {
              
              #define ToNSString_VALUE(value) \
              case value: return @#value
              
              #define ToNSString_END(T) \
              } \
              return @"(unknown)"; \
              }
              
              // NSString* UIInterfaceOrientationToNSString(UIInterfaceOrientation);
              ToNSString_BEGIN(UIInterfaceOrientation);
              ToNSString_VALUE(UIInterfaceOrientationPortrait);           // 1
              ToNSString_VALUE(UIInterfaceOrientationPortraitUpsideDown); // 2
              ToNSString_VALUE(UIInterfaceOrientationLandscapeLeft);      // 3
              ToNSString_VALUE(UIInterfaceOrientationLandscapeRight);     // 4
              ToNSString_END  (UIInterfaceOrientation);
              
              // NSString* UIDeviceOrientationToNSString(UIDeviceOrientation);
              ToNSString_BEGIN(UIDeviceOrientation);
              ToNSString_VALUE(UIDeviceOrientationUnknown);               // 0
              ToNSString_VALUE(UIDeviceOrientationPortrait);              // 1
              ToNSString_VALUE(UIDeviceOrientationPortraitUpsideDown);    // 2
              ToNSString_VALUE(UIDeviceOrientationLandscapeLeft);         // 3
              ToNSString_VALUE(UIDeviceOrientationLandscapeRight);        // 4
              ToNSString_VALUE(UIDeviceOrientationFaceUp);                // 5
              ToNSString_VALUE(UIDeviceOrientationFaceDown);              // 6
              ToNSString_END  (UIDeviceOrientation);
              
              
              
              // Change this custom method to alter auto-rotation behavior on all supported iOS versions and platforms.
              - (BOOL)allowAutoRotate:(UIInterfaceOrientation)interfaceOrientation
              {
                  NSUInteger interfaceOrientationAsMask = (1<<interfaceOrientation);
                  return interfaceOrientationAsMask & [self supportedInterfaceOrientations];
              }
              
              // Reads from the project's-Info.plist
              - (NSUInteger)supportedInterfaceOrientations
              {
                  static NSUInteger orientationsResult;
              
                  if (!orientationsResult) {
                      NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];
              
                      for (id orientationString in supportedOrientations) {
                          if ([orientationString isEqualToString:@"UIInterfaceOrientationPortrait"]) {
                              orientationsResult |= UIInterfaceOrientationMaskPortrait;
                              NSLog(@"Supported orientation: Portrait");
                          } else if ([orientationString isEqualToString:@"UIInterfaceOrientationPortraitUpsideDown"]) {
                              orientationsResult |= UIInterfaceOrientationMaskPortraitUpsideDown;
                              NSLog(@"Supported orientation: Portrait (upside-down)");
                          } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeRight"]) {
                              orientationsResult |= UIInterfaceOrientationMaskLandscapeRight;
                              NSLog(@"Supported orientation: Landscape (home button on the left)");
                          } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeLeft"]) {
                              orientationsResult |= UIInterfaceOrientationMaskLandscapeLeft;
                              NSLog(@"Supported orientation: Landscape (home button on the right)");
                          } else {
                              NSLog(@"Unrecognized orientation '%@' in mainBundle plist, key UISupportedInterfaceOrientations", orientationString);
                          }
                      }
                  }
                 return orientationsResult;
              }
              
              // iOS 6+ (not yet used in 6.0.1)
              - (BOOL)shouldAutorotate
              {
                  UIDeviceOrientation interfaceOrientationFromDevice = [UIDevice currentDevice].orientation;
                  BOOL result = [self allowAutoRotate:interfaceOrientationFromDevice];
                  NSString *currentDeviceOrientation = UIDeviceOrientationToNSString(interfaceOrientationFromDevice);
                  NSLog(@"shouldAutorotate: %s (current orientation %@)", result ? "YES" : "NO", currentDeviceOrientation);
                  return result;
              }
              
              // iOS 2.0 - 5.1 (iOS 6+ deprecated, 6.0.1 still works)
              - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
              {
                  NSString* orientationString;
                  UIDeviceOrientation interfaceOrientationFromDevice = [UIDevice currentDevice].orientation;
              
                  if ((int)interfaceOrientation != (int)interfaceOrientationFromDevice) {
                      orientationString = [NSString stringWithFormat:@"current device orientation: %@, interface orientation wants: %@",
                                           UIDeviceOrientationToNSString(interfaceOrientationFromDevice),
                                           UIInterfaceOrientationToNSString(interfaceOrientation)
                                           ];
                  } else {
                      orientationString = [NSString stringWithFormat:@"device orientation: %@", UIDeviceOrientationToNSString(interfaceOrientationFromDevice)
                                           ];
                  }
              
                  BOOL result = [self allowAutoRotate:interfaceOrientation];
                  NSLog(@"shouldAutorotateToInterfaceOrientation: %s (%@)",
                        result ? "YES" : "NO",
                        orientationString);
                  return result;
              }
              

              仍然存在不使用当前方向的 segue 动画的烦人问题。我的猜测是,对每个 VC 进行子类化并在 push/notify delegate on pop 上放置一些方向是可行的方法。

              同样重要:

              shouldAutorotateToInterfaceOrientation doesn't work

              tabBarController and navigationControllers in landscape mode, episode II

              【讨论】:

                【解决方案14】:

                试试这个。这对我有用。粗糙的当时 didfinishedlaunch 方法没有检测到设备方向。它默认为肖像。所以。我用来检查统计栏方向。我测试这段代码。把它放在appdeleget中的didfinishedlaunch方法中。

                UIInterfaceOrientation 方向 = [UIApplication sharedApplication].statusBarOrientation;

                if(orientation == 0) {//Default orientation
                    //UI is in Default (Portrait) -- this is really a just a failsafe.
                
                    NSLog("for portrait");
                
                
                }else if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
                {
                
                    NSLog("portrait");
                }else if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
                {
                
                    NSLog("Landscap");
                }
                

                【讨论】:

                  【解决方案15】:

                  试试这个 [[UIApplication sharedApplication] statusBarOrientation];

                  或者在应用委托中实现这个

                  (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
                  {
                      UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
                  }
                  

                  有效

                  【讨论】:

                    【解决方案16】:

                    上面的每个人都发布了非常有效的答案:但作为更新:Apple 的看法:您应该使用 UIStatusBar 方向来读取设备的当前方向:

                    检查设备当前方向的一种方法是在 viewDidLoad 方法中使用 int 值:

                        int orientationType = [[UIDevice currentDevice] orientation];
                    

                    在哪里考虑以下。 . . - 1 = 肖像(向上) - 2 = 纵向倒置 - 3 = 风景(右) - 4 = 风景(左)

                    然后您可以在检测到方向后使用IF 语句调用方法,依此类推:

                    希望这对某人有点帮助

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2013-10-10
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-05-03
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多