objective-c 如何在旋转前检测 iPhone 方向

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1160620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:56:57  来源:igfitidea点击:

how do I detect the iPhone orientation before rotating

iphoneobjective-ccocoa-touchiphone-sdk-3.0

提问by

In my program I'm moving things based on rotation, but I'm not rotating the entire view. I'm Using :

在我的程序中,我根据旋转来移动事物,但我没有旋转整个视图。我正在使用 :

  static UIDeviceOrientation previousOrientation = UIDeviceOrientationPortrait;

 - (void)applicationDidFinishLaunching:(UIApplication *)application {   
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
    [[NSNotificationCenter defaultCenter] addObserver:self
           selector:@selector(didRotate:)
           name:@"UIDeviceOrientationDidChangeNotification" object:nil];

}

- (void) didRotate:(NSNotification *)notification{  
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

    [self doRotationStuff:orientation: previousOrientation];
previousOrientation = orientation;

} 

This works as long as, when the program is launched, the device orientation is portrait, but not if the initial orientation is landscape or upside down, because [self doRotationStuff] makes changes relative to the difference from the previous orientation.

只要在程序启动时设备方向是纵向的,这就会起作用,但如果初始方向是横向或颠倒,则无效,因为 [self doRotationStuff] 相对于与先前方向的差异进行了更改。

Is there a way to detect the orientation either at launch, or right before the device is rotated?

有没有办法在启动时或在设备旋转之前检测方向?

回答by delany

Depending on your circumstances, a simpler option may be the interfaceOrientation property of the UIViewController class. This is correct before a rotation.

根据您的情况,更简单的选项可能是 UIViewController 类的 interfaceOrientation 属性。这在旋转之前是正确的。

回答by Daniel Dickison

Updated:

更新:

So, from the comment discussion, it appears that you can't rely on [UIDevice currentDevice].orientationuntil the orientation actually changes for the first time. If so, you could probably hack it by getting raw accelerometer readings.

因此,从评论讨论来看,您似乎无法依赖,[UIDevice currentDevice].orientation直到方向第一次真正发生变化。如果是这样,您可能可以通过获取原始加速度计读数来破解它。

#define kUpdateFrequency 30  // Hz
#define kUpdateCount 15 // So we init after half a second
#define kFilteringFactor (1.0f / kUpdateCount)

- (void)applicationDidFinishLaunching:(UIApplication *)app
{
    [UIAccelerometer sharedAccelerometer].updateInterval = (1.0 / kUpdateFrequency);
    [UIAccelerometer sharedAccelerometer].delegate = self;
    accelerometerCounter = 0;
    ...
}

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)accel
{
    // Average out the first kUpdateCount readings
    // acceleration_[xyz] are ivars typed float
    acceleration_x = (float)accel.x * kFilteringFactor + acceleration_x * (1.0f - kFilteringFactor);
    acceleration_y = (float)accel.y * kFilteringFactor + acceleration_y * (1.0f - kFilteringFactor);
    acceleration_z = (float)accel.z * kFilteringFactor + acceleration_z * (1.0f - kFilteringFactor);

    accelerometerCounter++;
    if (accelerometerCounter == kUpdateCount)
    {
        [self initOrientation];
        [UIAccelerometer sharedAccelerometer].delegate = nil;
    }
}

- (void)initOrientation
{
    // Figure out orientation from acceleration_[xyz] and set up your UI...
}


Original response:

原回复:

Does [UIDevice currentDevice].orientationreturn the correct orientation during applicationDidFinishLaunching:? If so, you can set up your initial UI according to that orientation.

[UIDevice currentDevice].orientation期间是否返回正确的方向applicationDidFinishLaunching:?如果是这样,您可以根据该方向设置初始 UI。

If that property doesn't get set until some later time, you might try experimenting with performSelector:afterDelay:to initialize the UI after a small delay.

如果该属性直到稍后才设置,您可以尝试尝试performSelector:afterDelay:在一小段延迟后初始化 UI。

This code sample is from Kendall's answer below, added here for completeness:

此代码示例来自下面 Kendall 的回答,为了完整起见,在此处添加:

[self performSelector:@selector(getOriented) withObject:nil afterDelay:0.0f];

I'm not sure if a zero-second delay is sufficient -- this means the code for getOrientedwill run during the first pass through the event run loop. You may need to wait longer for the accelerometer readings to register on UIDevice.

我不确定零秒延迟是否足够——这意味着代码getOriented将在第一次通过事件运行循环时运行。您可能需要等待更长时间才能在 上注册加速度计读数UIDevice

回答by h4xxr

Mort, these answers seem somewhat of a red herring; I can't see why you can't use the following built-in method for a UIViewController class:

Mort,这些答案似乎有点牵强;我不明白为什么不能对 UIViewController 类使用以下内置方法:

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {}

This method gets called automatically after a rotation has occurred (rather than with shouldAutorotateToInterfaceOrientation which only tells you it's about to happen). Handily, the variable 'fromInterfaceOrientation' contains the previous orientation. As the documentation also says, you can assume that the interfaceOrientation property of the view has already been set to the new orientation, so you then have one method with access to the old orientation and the new!

在发生旋转后会自动调用此方法(而不是使用 shouldAutorotateToInterfaceOrientation 只告诉您它即将发生)。方便的是,变量“fromInterfaceOrientation”包含先前的方向。正如文档中所说,您可以假设视图的 interfaceOrientation 属性已设置为新方向,因此您可以使用一种方法访问旧方向和新方向!

If I've missed something and you've already dismissed being able to use this method, my apologies! It just seems odd that you're creating and storing a variable for the "previous orientation" when it's provided for free in the above method.

如果我遗漏了什么而您已经拒绝使用这种方法,我很抱歉!当在上述方法中免费提供时,您正在为“先前方向”创建和存储变量,这似乎很奇怪。

Hope that helps!

希望有帮助!

回答by cynistersix

Use this for the orientation of the UI if you need to determine what way are you pointing.

如果您需要确定指向的方向,请将此用于 UI 的方向。

Not 100% sure this is right but going off the top of my head:

不是 100% 确定这是正确的,但我的头顶是:

[[[UIApplication sharedApplication] statusBar] orientation]

回答by Ray

Here's one way to get the orientation when the app first loads and the UIDeviceOrientation is set to UIDeviceOrientationUnknown. You can look at the transform property of the rotated view.

这是在应用程序首次加载且 UIDeviceOrientation 设置为 UIDeviceOrientationUnknown 时获取方向的一种方法。您可以查看旋转视图的变换属性。

if(toInterface == UIDeviceOrientationUnknown) {
    CGAffineTransform trans = navigationController.view.transform;
    if(trans.b == 1 && trans.c == -1)
        toInterface = UIDeviceOrientationLandscapeLeft;
    else if(trans.b == -1 && trans.c == 1)
        toInterface = UIDeviceOrientationLandscapeRight;
    else if(trans.a == -1 && trans.d == -1)
        toInterface = UIDeviceOrientationPortraitUpsideDown;
    else
        toInterface = UIDeviceOrientationPortrait;
}

回答by luvieere

A more complete example on how to obtain device orientation from accelerator readings can be found hereAs the solution relies on accelerator readings, it wouldn't work on the simulator, so you'll have to work on the device... still looking myself for a solution that works on the simulator.

关于如何从加速器读数获取设备方向的更完整示例可以在此处找到 由于该解决方案依赖于加速器读数,因此无法在模拟器上运行,因此您必须在设备上工作...仍在寻找自己对于适用于模拟器的解决方案。

回答by Kendall Helmstetter Gelner

In response to your comment, I thought I could better put code here than in a comment (though really Daniel deserves credit here):

为了回应您的评论,我认为我可以将代码放在这里比在评论中更好(尽管 Daniel 在这里确实值得称赞):

in applicationDidFinishLaunching:

在 applicationDidFinishLaunching 中:

[self performSelector:@selector(getOriented) withObject:nil afterDelay:0.0f];

Then you just need the method to call:

然后你只需要调用的方法:

- (void) getOriented 
{ 
   UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
   // save orientation somewhere
}