这是一个基于 zic10 答案的快速版本,添加了一个标志,即使该处理程序中的第一行是motionManager.stopDeviceMotionUpdates()
.
此外,3.0
如果您想忽略抖动但检测到颠簸,则 around 值可能很有用。我发现0.3
它太低了,因为它最终更像是“检测移动”。在我的测试中,范围更像:
- 0.75 - 2.49 是更好的抖动灵敏度范围
- 2.5 - 5.0 是“忽略抖动,检测碰撞”的好范围
这是 Xcode 单一 VC 模板的完整视图控制器:
import UIKit
import CoreMotion
class ViewController: UIViewController {
lazy var motionManager: CMMotionManager = {
return CMMotionManager()
}()
let accelerationThreshold = 3.0
var handlingShake = false
override func viewWillAppear(animated: Bool) {
handlingShake = false
motionManager.startDeviceMotionUpdatesToQueue(NSOperationQueue.currentQueue()!) { [weak self] (motion, error) in
if
let userAcceleration = motion?.userAcceleration,
let _self = self {
print("\(userAcceleration.x) / \(userAcceleration.y)")
if (fabs(userAcceleration.x) > _self.accelerationThreshold
|| fabs(userAcceleration.y) > _self.accelerationThreshold
|| fabs(userAcceleration.z) > _self.accelerationThreshold)
{
if !_self.handlingShake {
_self.handlingShake = true
_self.handleShake();
}
}
} else {
print("Motion error: \(error)")
}
}
}
override func viewWillDisappear(animated: Bool) {
// or wherever appropriate
motionManager.stopDeviceMotionUpdates()
}
func handleShake() {
performSegueWithIdentifier("showShakeScreen", sender: nil)
}
}
我用于此测试的情节提要如下所示:
还值得注意的是,CoreMotion 在模拟器中是不可测试的。由于这个限制,您可能仍然发现额外实现检测运动抖动的 UIDevice 方法是值得的。这将允许您在模拟器中手动测试摇动或让 UITests 访问摇动以进行测试或诸如 fastlane 的快照之类的工具。就像是:
class ViewController: UIViewController {
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
becomeFirstResponder()
}
override func canBecomeFirstResponder() -> Bool {
return true
}
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
if TARGET_OS_SIMULATOR != 0 {
if event?.subtype == .MotionShake {
// do stuff
}
}
}
}
然后使用 Ctrl-Cmd-Z 在模拟器中测试抖动。