John Stephen John Stephen - 4 months ago 22
iOS Question

How do I adjust CMMotionManager data for orientation under iOS 8?

My application uses CMMotionManager to track device motion, but iOS always returns device motion data in the standard device orientation (home button at the bottom).

To get the motion data into the same orientation as my UIView, I accumulate the view transforms from my view down to the window like this:

CGAffineTransform transform = self.view.transform;
for (UIView *superview = self.view.superview; superview; superview = superview.superview) {
CGAffineTransform superviewTransform = superview.transform;
transform = CGAffineTransformConcat(transform, superviewTransform);
}


This transform gets calculated correctly under iOS 6 & 7, but iOS 8 changes the rotation model and now the views always return the identity transform (no rotation) no matter how the device is oriented. The data from the motion manager is still fixed in the standard orientation though.

Monitoring UIDevice rotation devices and manually calculating the four transforms seems like one approach to getting this transform under iOS 8, but it also seems bad since the device orientation won't necessarily match my view's orientation (ie, upside on iPhone is a device orientation not normally supported).

What's the best way to get the output from CMMotionManager into the orientation of a specific UIView under iOS 8?

Answer

I couldn't find a way to directly calculate the transform, so instead I changed my code to calculate set the transform manually when a willRotateToInterfaceOrientation: message is received in my view controller, like this:

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