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