Как настроить данные CMMotionManager для ориентации под iOS 8?

Мое приложение использует CMMotionManager для отслеживания движения устройства, но iOS всегда возвращает данные о движении устройства в стандартной ориентации устройства (кнопка "Домой" внизу).

Чтобы получить данные о движении в той же ориентации, что и мой UIView, я накапливаю трансформации вида из моего вида в окно следующим образом:

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

Это преобразование рассчитывается правильно в iOS 6 и 7, но iOS 8 меняет модель вращения, и теперь представления всегда возвращают преобразование идентичности (без вращения), независимо от того, как устройство ориентировано. Данные из диспетчера движения все еще фиксированы в стандартной ориентации.

Мониторинг уведомлений о ротации UIDevice и ручной расчет четырех преобразований кажется одним из подходов к получению этого преобразования в iOS 8, но это также кажется плохим, поскольку ориентация устройства не обязательно будет соответствовать ориентации моего вида (т. Е. Верхняя сторона iPhone - это ориентация устройства не нормально поддерживается).

Каков наилучший способ получить выходные данные из CMMotionManager для ориентации определенного UIView под iOS 8?

2 ответа

Решение

Я не смог найти способ непосредственно вычислить преобразование, поэтому вместо этого я изменил свой код для вычисления, установите преобразование вручную, когда в моем контроллере представления будет получено сообщение willRotateToInterfaceOrientation:

- (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 немного более гибок, когда вам нужно координировать анимированные переходы, например, при работе с графическими структурами или с использованием пользовательского макета.

Другие вопросы по тегам