这是一个基于zic10答案的Swift版本,增加了一个标志,可以防止在处理程序的第一行是时获取一些额外的调用。
此外,如果您想忽略晃动但检测到碰撞,则约3.0的值可能会很有用。在我的测试中,范围更像是:
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) {
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 {
}
}
}
}
然后使用Ctrl-Cmd-Z在模拟器中测试晃动效果。