简体   繁体   English

立即检测iOS方向的变化

[英]Detecting iOS orientation change instantly

I have a game in which the orientation of the device affects the state of the game. 我有一个游戏,其中设备的方向影响游戏的状态。 The user must quickly switch between Landscape, Portrait, and Reverse Landscape orientations. 用户必须在横向,纵向和反向横向方向之间快速切换。 So far I've been registering the game for orientation notifications via: 到目前为止,我一直在通过以下方式注册游戏以获取方向通知:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

But it is far too slow - there seems to be about a second delay between rotating the phone and the notification actually being fired. 但它太慢了 - 旋转电话和通知实际被解雇之间似乎有大约第二个延迟。 I need a way to INSTANTLY detect changes in the device's orientation. 我需要一种方法来立即检测设备方向的变化。 I have tried experimenting with the gyroscope, but am not yet familiar enough with it to know whether or not it is the solution I am looking for. 我已经尝试过使用陀螺仪进行试验,但我还不熟悉它,以了解它是否是我正在寻找的解决方案。

Add a notifier in the viewWillAppear function viewWillAppear函数中添加通知程序

-(void)viewWillAppear:(BOOL)animated{
  [super viewWillAppear:animated];
  [[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(orientationChanged:)    name:UIDeviceOrientationDidChangeNotification  object:nil];
}

The orientation change notifies this function 方向改变通知此功能

- (void)orientationChanged:(NSNotification *)notification{
   [self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}

which in-turn calls this function where the moviePlayerController frame is orientation is handled 进而调用此函数处理moviePlayerController框架的方向

- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {

    switch (orientation)
    {
        case UIInterfaceOrientationPortrait:
        case UIInterfaceOrientationPortraitUpsideDown:
        { 
        //load the portrait view    
        }

            break;
        case UIInterfaceOrientationLandscapeLeft:
        case UIInterfaceOrientationLandscapeRight:
        {
        //load the landscape view 
        }
            break;
        case UIInterfaceOrientationUnknown:break;
    }
}

in viewDidDisappear remove the notification viewDidDisappear删除通知

-(void)viewDidDisappear:(BOOL)animated{
   [super viewDidDisappear:animated];
   [[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}

I guess this is the fastest u can have changed the view as per orientation 我想这是你可以根据方向更改视图最快速度

That delay you're talking about is actually a filter to prevent false (unwanted) orientation change notifications. 您正在谈论的延迟实际上是一个过滤器,以防止错误(不需要的)方向更改通知。

For instant recognition of device orientation change you're just gonna have to monitor the accelerometer yourself. 立即识别设备方向变化,您只需要自己监控加速度计。

Accelerometer measures acceleration (gravity included) in all 3 axes so you shouldn't have any problems in figuring out the actual orientation. 加速度计测量所有3个轴的加速度(包括重力),因此在确定实际方向时不应该有任何问题。

Some code to start working with accelerometer can be found here: 可以在此处找到一些开始使用加速度计的代码:

How to make an iPhone App – Part 5: The Accelerometer 如何制作iPhone应用程序 - 第5部分:加速度计

And this nice blog covers the math part: 这个不错的博客涵盖了数学部分:

Using the Accelerometer 使用加速度计

Why you didn`t use 为什么你没用

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

?

Or you can use this 或者你可以使用它

-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

Or this 或这个

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

Hope it owl be useful ) 希望它有用)

For my case handling UIDeviceOrientationDidChangeNotification was not good solution as it is called more frequent and UIDeviceOrientation is not always equal to UIInterfaceOrientation because of (FaceDown, FaceUp). 对于我的办案UIDeviceOrientationDidChangeNotification并不像它被称为更频繁和更良好的解决方案UIDeviceOrientation并不总是等于UIInterfaceOrientation因为(面朝下,面朝上)的。

I handle it using UIApplicationDidChangeStatusBarOrientationNotification : 我使用UIApplicationDidChangeStatusBarOrientationNotification处理它:

//To add the notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeOrientation:)

//to remove the
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];

 ...

- (void)didChangeOrientation:(NSNotification *)notification
{
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;

    if (UIInterfaceOrientationIsLandscape(orientation)) {
        NSLog(@"Landscape");
    }
    else {
        NSLog(@"Portrait");
    }
}

Try making your changes in: 尝试进行以下更改:

- (void) viewWillLayoutSubviews {}

The code will run at every orientation change as the subviews get laid out again. 随着子视图再次布局,代码将在每个方向更改时运行。

@vimal answer did not provide solution for me. @vimal答案没有为我提供解决方案。 It seems the orientation is not the current orientation, but from previous orientation. 看起来方向不是当前的方向,而是来自之前的方向。 To fix it, I use [[UIDevice currentDevice] orientation] 要修复它,我使用[[UIDevice currentDevice] orientation]

- (void)orientationChanged:(NSNotification *)notification{
    [self adjustViewsForOrientation:[[UIDevice currentDevice] orientation]];
}

Then 然后

- (void) adjustViewsForOrientation:(UIDeviceOrientation) orientation { ... }

With this code I get the current orientation position. 使用此代码,我获得当前的方向位置。

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

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