Я использую CMMotionManager, чтобы получить отношение к устройству, и столкнулся с особой проблемой, когда он работает отлично при первом запуске, но после остановки и запуска он дает удвоенные числа для рыскания.Почему CMMotionManager сообщает о некорректном рыскании после остановки и перезапуска?
Я начинаю с startDeviceMotionUpdates(using: .xTrueNorthZVertical)
и проверяет значения рыскания в цикле рендеринга сцены SceneKit. Если я положил телефон на стол и повернул его на 90 °, он показал изменение на 90 ° в рыскании. Отлично.
Если я остановлю его, используя stopDeviceMotionUpdates()
, запустите его снова и выполните то же вращение на 90 °, я ожидаю увидеть такое же изменение на 90 °. Но вместо этого он показывает 180 ° вращения!
Это похоже на то, что это происходит при первом запуске с синтаксисом (using:)
. Я тестирую его на iPhone 5 с iOS 10.0.2, используя xCode 8.0.
Чтобы воссоздать, создать новый проект с помощью «Игра» шаблон и заменить код в GameViewController.swift со следующим:
import UIKit
import SceneKit
import CoreMotion
class GameViewController: UIViewController, SCNSceneRendererDelegate {
static let motionManager = CMMotionManager()
var scnView: SCNView!
var scnScene: SCNScene!
override func viewDidLoad() {
super.viewDidLoad()
scnView = self.view as! SCNView
scnView.delegate = self
scnScene = SCNScene()
scnView.scene = scnScene
scnView.isPlaying = true
GameViewController.motionManager.startDeviceMotionUpdates(using: .xTrueNorthZVertical)
// stop and start it again to cause doubling
GameViewController.motionManager.stopDeviceMotionUpdates()
GameViewController.motionManager.startDeviceMotionUpdates(using: .xTrueNorthZVertical)
}
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
if let motion = GameViewController.motionManager.deviceMotion {
print(Int(motion.attitude.yaw * 180/M_PI))
}
}
}
Этот код начинается CMMotionManger, то немедленно останавливает его и запускает его снова. Поверните телефон на 90 °, и вы увидите, что он показывает 180 ° рыскания. Очевидно, что это не практический пример, просто упрощенная версия, которая показывает проблему. В моем фактическом использовании я останавливаю CMMotionManager, когда представление SceneKit, в котором я его использую, отклоняется и перезапускает его, когда открывается другое представление SceneKit.
На данный момент мое обходное решение - никогда не останавливать CMMotionManager после его запуска. Он работает, но в документации конкретно говорится: «You должен call stopDeviceMotionUpdates(), когда вы больше не хотите, чтобы ваше приложение обрабатывало обновления движений устройства». Это не похоже на отличное решение.
Почему CMMotionManager дает неправильные значения после остановки и запуска, и что я могу сделать, чтобы исправить это?
В моем фактическом прецеденте я останавливаю CMMotionManager, когда вид SceneKit, в котором я его использую, отклоняется, а затем перезапускает его, если/когда открывается другое представление SceneKit. Пример в моем вопросе - это лишь минимальный пример, который показывает проблему. – Robert