检测iOS设备旋转方向的变化方法

54

我有一个游戏,设备的方向会影响游戏的状态。用户必须快速在横屏、竖屏和反向横屏之间切换。到目前为止,我一直通过以下方式注册游戏以获取方向通知:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
但速度太慢了 - 在旋转手机和通知实际触发之间似乎有约一秒的延迟。我需要一种立即检测设备方向变化的方法。我尝试过使用陀螺仪进行实验,但还不够熟悉它,不知道它是否是我寻找的解决方案。

请看这里,使用这个链接。如有疑问,请告诉我。 - Sanoj Kashyap
非常好的文章:http://tech-blog.maddyzone.com/javascript/detect-orientation-event - Rituraj ratan
6个回答

144

viewWillAppear函数中添加一个通知器

-(void)viewWillAppear:(BOOL)animated{
  [super viewWillAppear:animated];
  [[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(orientationChanged:)    name:UIDeviceOrientationDidChangeNotification  object:nil];
}
方向变化会通知这个函数。
- (void)orientationChanged:(NSNotification *)notification{
   [self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}

这将调用此函数,在该函数中将处理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;
    }
}
viewDidDisappear中移除通知。
-(void)viewDidDisappear:(BOOL)animated{
   [super viewDidDisappear:animated];
   [[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}

我猜这是你能根据方向最快改变视图的方法


4
在复制粘贴时,像真正的程序员一样不要忘记使用[super viewWillAppear:animated]和[super viewDidDisappear:animated]。 - Dog
注意:UIDeviceOrientation!= UIInterfaceOrientation。 - nnrales

25

你所说的延迟实际上是为了避免误报(不必要的)设备方向更改通知的过滤器。

对于立即识别设备方向更改,您需要自己监视加速计。

加速计可以测量所有三个轴(包括重力)的加速度,因此您应该没有任何问题来确定实际方向。

一些与加速计开始工作的代码可以在此处找到:

如何制作iPhone应用程序 - 第5部分:加速度计

这篇很好的博客涵盖了数学部分:

使用加速度计


1
UIAccelerometer已被弃用,现已被Core Motion取代。 - Leo Dabus
1
第二个链接已经失效。 - Rob Norback

20
为什么你没有使用 < /p>?
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

或者你可以使用这个

-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
或者是这个

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
希望它会有用,愿你受益。

8
这些方法不会自动在子视图控制器上调用。 - Neal Ehardt
3
这些方法现在已被弃用。 - Satyam

12

对我来说,处理UIDeviceOrientationDidChangeNotification并不是一个好的解决方案,因为它被频繁调用,而且由于(FaceDown, FaceUp)的存在,UIDeviceOrientation并不总是等于UIInterfaceOrientation

我使用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");
    }
}

6
尝试在以下方法中进行更改:- (void) viewWillLayoutSubviews {}。此代码将在每次方向更改时运行,因为子视图会再次布局。

5

@vimal的答案对我来说并没有提供解决方案。似乎方向不是当前方向,而是之前的方向。为了解决这个问题,我使用了[[UIDevice currentDevice] orientation]

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

那么

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

使用此代码,可以获取当前方向位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接