如何调整CMMotionManager数据以适应iOS 8下的方向?

如何调整CMMotionManager数据以适应iOS 8下的方向?,ios,uikit,ios8,cmmotionmanager,Ios,Uikit,Ios8,Cmmotionmanager,我的应用程序使用CMMotionManager跟踪设备运动,但iOS总是以标准设备方向(底部的home按钮)返回设备运动数据 为了使运动数据与UIView的方向相同,我积累了从我的视图到窗口的视图变换,如下所示: CGAffineTransform transform = self.view.transform; for (UIView *superview = self.view.superview; superview; superview = superview.superview) {

我的应用程序使用CMMotionManager跟踪设备运动,但iOS总是以标准设备方向(底部的home按钮)返回设备运动数据

为了使运动数据与UIView的方向相同,我积累了从我的视图到窗口的视图变换,如下所示:

CGAffineTransform transform = self.view.transform;
for (UIView *superview = self.view.superview; superview; superview = superview.superview) {
    CGAffineTransform superviewTransform = superview.transform;
    transform = CGAffineTransformConcat(transform, superviewTransform);
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    CGAffineTransform transform;
    switch (toInterfaceOrientation) {
        case UIInterfaceOrientationLandscapeLeft:
            transform = CGAffineTransformMake(
                0, -1,
                1, 0,
                0, 0);
            break;

        case UIInterfaceOrientationLandscapeRight:
            transform = CGAffineTransformMake(
                0, 1,
                -1, 0,
                0, 0);
            break;

        case UIInterfaceOrientationPortraitUpsideDown:
            transform = CGAffineTransformMake(
                -1, 0,
                0, -1,
                0, 0);
            break;

        case UIInterfaceOrientationPortrait:
            transform = CGAffineTransformIdentity;
            break;
    }
    self.motionTransform = transform;
}
在iOS 6和iOS 7下可以正确计算此转换,但是iOS 8更改了旋转模型,现在无论设备的方向如何,视图都会返回标识转换(无旋转)。但是,来自运动管理器的数据仍然固定在标准方向上

在iOS 8下,监视UIDevice rotation通知并手动计算这四个转换似乎是获得此转换的一种方法,但它似乎也很糟糕,因为设备方向不一定与我的视图的方向匹配(即,iPhone上的上方向是通常不支持的设备方向)


在iOS 8下,将CMMotionManager的输出转换为特定UIView方向的最佳方法是什么?

我找不到直接计算转换的方法,因此我更改了代码,以便在视图控制器中收到willRotateToInterfaceOrientation:消息时手动计算并设置转换,如下所示:

CGAffineTransform transform = self.view.transform;
for (UIView *superview = self.view.superview; superview; superview = superview.superview) {
    CGAffineTransform superviewTransform = superview.transform;
    transform = CGAffineTransformConcat(transform, superviewTransform);
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    CGAffineTransform transform;
    switch (toInterfaceOrientation) {
        case UIInterfaceOrientationLandscapeLeft:
            transform = CGAffineTransformMake(
                0, -1,
                1, 0,
                0, 0);
            break;

        case UIInterfaceOrientationLandscapeRight:
            transform = CGAffineTransformMake(
                0, 1,
                -1, 0,
                0, 0);
            break;

        case UIInterfaceOrientationPortraitUpsideDown:
            transform = CGAffineTransformMake(
                -1, 0,
                0, -1,
                0, 0);
            break;

        case UIInterfaceOrientationPortrait:
            transform = CGAffineTransformIdentity;
            break;
    }
    self.motionTransform = transform;
}

虽然不是很明显,但在iOS 8及更高版本中,建议使用过渡协调员来实现这一点

viewWillTransition(to:with:)
中,协调器可以在其调用的任何方法的完成块中向您传递采用
UIViewControllerTransitionCoordinatorContext
的对象(UIKit使用的默认协调器实际上是它自己的上下文,但不一定如此)

上下文的
targetTransform
属性是动画结束时应用于界面的旋转。注意,这是一个相对变换,而不是接口的最终绝对变换

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    let animation: (UIViewControllerTransitionCoordinatorContext) -> Void = { context in
        // Update animatable properties.
    }

    coordinator.animate(alongsideTransition: animation) { context in
        // Store or use the transform.
        self.mostRecentTransform = context.targetTransform
    }
}

虽然旧方法仍然有效,但当您需要协调动画过渡时,例如使用图形框架或使用自定义布局时,此API会更加灵活。

感谢您的帮助