简体   繁体   English

iOS:设备加载方向

[英]iOS: Device orientation on load

It seems that when my app loads, it does not know its current orientation:似乎当我的应用程序加载时,它不知道它的当前方向:

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

Once I rotate the device, I get a correct orientation, but when I load the app, without changing the orientation, it seems that using [[UIDevice currentDevice] orientation] doesn't know the current orientation.旋转设备后,我得到了正确的方向,但是当我加载应用程序时,在不更改方向的情况下,似乎使用[[UIDevice currentDevice] orientation]不知道当前方向。

Is there another way to check this when I first load my app?当我第一次加载我的应用程序时,还有其他方法可以检查吗?

EDIT: I mis-read your question.编辑:我误读了你的问题。 This will allow you to start your application in certain orientations.这将允许您以特定方向启动应用程序。 Just realized you're trying to figure out the orientation on launch.刚刚意识到您正在尝试确定启动时的方向。

There is a method to check the status bar orientation on UIApplication :有一种方法可以检查UIApplication上的状态栏方向:

[[UIApplication sharedApplication] statusBarOrientation];

Original answer原始答案

Try setting the application's accepted device orientations in the plist file:尝试在 plist 文件中设置应用程序接受的设备方向:

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

This will indicate that your application supports Portrait (home button at the bottom), landscape left, and landscape right.这将表明您的应用程序支持纵向(底部的主页按钮)、横向左侧和横向右侧。

Then, in your UIViewControllers, you will need to override the shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) method to return YES when the app should rotate:然后,在您的 UIViewControllers 中,您需要重写shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)方法以在应用程序旋转时返回 YES:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

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

This will tell the UIViewController to auto rotate if the device is in one of your supported orientations.如果设备处于您支持的方向之一,这将告诉 UIViewController 自动旋转。 If you wanted to support the upside-down orientation as well (portrait with home button on top) then add that to your plist and just return YES out of this method.如果您也想支持倒置方向(顶部带有主页按钮的肖像),请将其添加到您的 plist 中,然后在此方法中返回 YES。

Let us know how it works out.让我们知道它是如何工作的。

I think this will work:我认为这会起作用:

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

According to the UIDevice reference:根据 UIDevice 参考:
Quote:引用:
"The value of this property always returns 0 unless orientation notifications have been enabled by calling beginGeneratingDeviceOrientationNotifications" “除非已通过调用 beginGeneratingDeviceOrientationNotifications 启用了方向通知,否则此属性的值始终返回 0”
I had initially assumed that this property contained the current orientation at all times, but not so, apparently.我最初假设此属性始终包含当前方向,但显然并非如此。 I guess that turning on notifications is being handled for us behind the scenes in other situations where the orientation property is typically accessed, so it wasn't obvious that this needs to be done manually inside the app delegate我猜想在通常访问方向属性的其他情况下,在幕后为我们处理打开通知,因此这需要在应用程序委托中手动完成并不明显

for those who looking answer for Swift 3 or 4. just add that code inside of viewDidLoad() block.对于那些寻找 Swift 3 或 4 的答案的人。只需在 viewDidLoad() 块内添加该代码。

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

update for depreciation alerts for IOS 13 and Swift 5.x use code block below. 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
    }
    }

You can do it by inserting the following notification inside您可以通过在里面插入以下通知来做到这一点

-(void)viewDidLoad

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

then put the following method inside your class然后将以下方法放入您的 class

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

The above method will check the orientation of the status bar of the ipad or iPhone and according to it you make do your animation in the required orientation.上述方法将检查 ipad 或 iPhone 的状态栏的方向,并根据它在所需的方向上执行 animation。

On load the device orientation can be .Unknown or .FaceUp .加载时,设备方向可以是.Unknown.FaceUp To figure out whether it's portrait or landscape I use the statusBarOrientation as a back-up, like this:为了弄清楚它是纵向还是横向,我使用statusBarOrientation作为备份,如下所示:

    var portraitOrientation = UIDevice.currentDevice().orientation == .Portrait

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

This way I can assure that portraitOrientation always tells me if the device is in portrait mode, and if not it will be in landscape.这样我可以确保 PortraitOrientation 总是告诉我设备是否处于portraitOrientation模式,如果不是,它将处于横向模式。 Even on loading the app for the first time.即使是第一次加载应用程序。

One thing that nobody has touched on yet is that you're storing UIDeviceOrientation types in a UIInterfaceOrientation variable.还没有人提到的一件事是您将UIDeviceOrientation类型存储在UIInterfaceOrientation变量中。 They are different, and should not be treated as equal.它们是不同的,不应被视为平等。 Note that UIDeviceOrientationLeft is equal to UIInterfaceOrientationRight (since the interface rotates the opposite way compared to the device).请注意, UIDeviceOrientationLeft等于UIInterfaceOrientationRight (因为与设备相比,界面旋转的方式相反)。

In order to obtain the orientation from the status bar it is also important to have the all the orientations enabled at the plist file.为了从状态栏获取方向,在 plist 文件中启用所有方向也很重要。

Swift 3 based on @Marjin 's code. 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
{

}

the problem is that [UIDevice currentDevice]orientation] sometimes reports the the device's orientation incorrectly.问题是[UIDevice currentDevice]orientation]有时会错误地报告设备的方向。

instead use [[UIApplication sharedApplication]statusBarOrientation] which is a UIInterfaceOrientation so to check it you'll need to use the UIInterfaceOrientationIsLandscape(orientation)而是使用[[UIApplication sharedApplication]statusBarOrientation]这是一个UIInterfaceOrientation所以要检查它你需要使用UIInterfaceOrientationIsLandscape(orientation)

hope this helps.希望这可以帮助。

I still use this working code snippet for iphone 4:我仍然将这个工作代码片段用于 iphone 4:

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

} }

This is the real answer.这是真正的答案。 When an app starts up, it's orientation is unknown.当应用程序启动时,它的方向是未知的。 It uses shouldAutorotateToInterfaceOrientation and supportedInterfaceOrientations to decide which orientation to pick.它使用 shouldAutorotateToInterfaceOrientation 和 supportedInterfaceOrientations 来决定选择哪个方向。

Watch as I start up a sample app in the iPhone 5.0 simulator and rotate it using the code below and 'Supported interface orientations' with all 4 possible orientations:观看我在 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)

I've seen lots of code snippets, but none of them work generically enough (iPad & iPhone, iOS 5.0+).我见过很多代码片段,但它们都不够通用(iPad 和 iPhone,iOS 5.0+)。

Instead of fumbling around with try-this-try-that, place the following in your root vc:与其在 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;
}

There is still a nagging problem of segue animations not using the current orientation.仍然存在不使用当前方向的 segue 动画的烦人问题。 My guess is that subclassing each VC and putting some orientation on push / notify delegate on pop would be the way to go.我的猜测是,将每个 VC 子类化并在 pop 上放置一些方向/通知委托将是 go 的方式。

Also important:也很重要:

shouldAutorotateToInterfaceOrientation doesn't work shouldAutorotateToInterfaceOrientation 不起作用

tabBarController and navigationControllers in landscape mode, episode II 横向模式下的 tabBarController 和 navigationControllers,第二集

Try this one.试试这个。 it's work for me.这对我有用。 gnarly at that time of didfinishedlaunch method not detect device orientation.粗糙的当时 didfinishedlaunch 方法没有检测到设备方向。 its take by default as a portrait.它默认为肖像。 so.所以。 i am using to check stats bar orientation.我用来检查统计栏方向。 i test this code.我测试这段代码。 put it in didfinishedlaunch method in appdeleget.把它放在appdeleget的didfinishedlaunch方法中。

UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 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");
}

Try This one [[UIApplication sharedApplication] statusBarOrientation];试试这个[[UIApplication sharedApplication] statusBarOrientation];

or implement this one in app delegate或在应用程序委托中实现这个

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

it works有用

Try the accelerometer to get its reading, UIAccelerometer, get sharedAccelerometer, set its delegate, get the readings, figure out from there orientation.尝试使用加速度计来获取它的读数,UIAccelerometer,获取 sharedAccelerometer,设置它的委托,获取读数,从那里找出方向。

Tried all and no good results.都试过了,没有好的结果。 So what I did, as I'm on an ipad, was to leave all the work to the splitViewController methods to invalidate the barButton:因此,当我在 ipad 上时,我所做的就是将所有工作留给 splitViewController 方法来使 barButton 无效:

For portrait:对于肖像:

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

For landscape:对于风景:

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

this always works on load.这始终适用于负载。

Everyone above posted very valid answers: but as an UPDATE: Apple's take: you should e using UIStatusBar orientations to read current orientation of the device:上面的每个人都发布了非常有效的答案:但作为更新:Apple 的看法:您应该使用 UIStatusBar 方向来读取设备的当前方向:

One way you could check the current orientation of the device is by using an int values as such, inside the viewDidLoad method:检查设备当前方向的一种方法是在viewDidLoad方法中使用 int 值:

    int orientationType = [[UIDevice currentDevice] orientation];

where consider the following.在哪里考虑以下内容。 . . . . - 1 = portrait (right way up) - 2 = portrait upside down - 3 = landscape (right) - 4 = landscape (left) - 1 = 纵向(右侧向上) - 2 = 纵向倒置 - 3 = 横向(右侧) - 4 = 横向(左侧)

and then you could use an IF statement to call a method after orientation is detected, so on and so forth:然后您可以在检测到方向后使用IF语句调用方法,依此类推:

Hope this was slightly helpful to someone希望这对某人有点帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM