Swift CoreMotion 在后台检测设备上的点击或敲击
Swift CoreMotion detect Tap or Knock on device while in background
我目前正在构建我的第一个 iOS Swift 应用程序,我想通过这个应用程序在后台 运行 时执行一个操作。
用户在设备上点击两次后需要执行该操作。
我已启用后台模式:应用功能中的位置更新
并在 AppDelegate 中设置一个 AccelerometerUpdatesToQueue 函数:
let manager = CMMotionManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if manager.accelerometerAvailable {
manager.accelerometerUpdateInterval = 0.01
manager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue()) {
[weak self] (data: CMAccelerometerData!, error: NSError!) in
println(data.acceleration.z)
}
}
return true
}
控制台按预期打印出 acceleration.z 值,但是一旦我按下主页按钮,控制台就会打印出停止。
我在网上搜索了有关如何执行此操作的示例代码,我知道这是可能的...因为我们都知道该应用程序 "Knock Knock to unlock",但我似乎找不到Swift.
的一段示例代码
我成功了!这是我的解决方案,请随时提出改进建议:)
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let manager = CMMotionManager()
var knocked : Bool = false
let motionUpdateInterval : Double = 0.05
var knockReset : Double = 2.0
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if manager.deviceMotionAvailable {
manager.deviceMotionUpdateInterval = motionUpdateInterval // seconds
manager.startDeviceMotionUpdatesToQueue(NSOperationQueue.mainQueue()) {
[weak self] (data: CMDeviceMotion!, error: NSError!) in
if (data.userAcceleration.z < -0.7) || (data.userAcceleration.z > 0.7) { // Check if device is knocked
// Check for double knock
if self!.knocked == false {
// First knock
println("First Knock")
self!.knocked = true
}else{
// Second knock
println("Double Knocked")
self!.knocked = false
self!.knockReset = 2.0
// Action:
}
}
// Countdown for reset action (second knock must be within the knockReset limit)
if (self!.knocked) && (self!.knockReset >= 0.0) {
self!.knockReset = self!.knockReset - self!.motionUpdateInterval
}else if self!.knocked == true {
self!.knocked = false
self!.knockReset = 2.0
println("Reset")
}
}
}
return true
}
感谢您发帖。尽管我需要弄清楚如何将这些数据与常规运动数据分开,但它正在帮助我。一个建议...使用 fabs 获取 userAcceleration.z 的绝对值。
if (data.userAcceleration.z < -0.7) || (data.userAcceleration.z > 0.7) { // Check if device is knocked
变成
if (fabs(data.userAcceleration.z) > 0.7) { // Check if device is knocked
在Swift5.1这一行:
manager.startDeviceMotionUpdatesToQueue(NSOperationQueue.mainQueue()) { [weak self] (data: CMDeviceMotion!, error: NSError!) in
需要:
manager.startDeviceMotionUpdates(to: .main) { [weak self] (data, error) in
我目前正在构建我的第一个 iOS Swift 应用程序,我想通过这个应用程序在后台 运行 时执行一个操作。
用户在设备上点击两次后需要执行该操作。
我已启用后台模式:应用功能中的位置更新
并在 AppDelegate 中设置一个 AccelerometerUpdatesToQueue 函数:
let manager = CMMotionManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
if manager.accelerometerAvailable {
manager.accelerometerUpdateInterval = 0.01
manager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue()) {
[weak self] (data: CMAccelerometerData!, error: NSError!) in
println(data.acceleration.z)
}
}
return true
}
控制台按预期打印出 acceleration.z 值,但是一旦我按下主页按钮,控制台就会打印出停止。
我在网上搜索了有关如何执行此操作的示例代码,我知道这是可能的...因为我们都知道该应用程序 "Knock Knock to unlock",但我似乎找不到Swift.
的一段示例代码我成功了!这是我的解决方案,请随时提出改进建议:)
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let manager = CMMotionManager()
var knocked : Bool = false
let motionUpdateInterval : Double = 0.05
var knockReset : Double = 2.0
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if manager.deviceMotionAvailable {
manager.deviceMotionUpdateInterval = motionUpdateInterval // seconds
manager.startDeviceMotionUpdatesToQueue(NSOperationQueue.mainQueue()) {
[weak self] (data: CMDeviceMotion!, error: NSError!) in
if (data.userAcceleration.z < -0.7) || (data.userAcceleration.z > 0.7) { // Check if device is knocked
// Check for double knock
if self!.knocked == false {
// First knock
println("First Knock")
self!.knocked = true
}else{
// Second knock
println("Double Knocked")
self!.knocked = false
self!.knockReset = 2.0
// Action:
}
}
// Countdown for reset action (second knock must be within the knockReset limit)
if (self!.knocked) && (self!.knockReset >= 0.0) {
self!.knockReset = self!.knockReset - self!.motionUpdateInterval
}else if self!.knocked == true {
self!.knocked = false
self!.knockReset = 2.0
println("Reset")
}
}
}
return true
}
感谢您发帖。尽管我需要弄清楚如何将这些数据与常规运动数据分开,但它正在帮助我。一个建议...使用 fabs 获取 userAcceleration.z 的绝对值。
if (data.userAcceleration.z < -0.7) || (data.userAcceleration.z > 0.7) { // Check if device is knocked
变成
if (fabs(data.userAcceleration.z) > 0.7) { // Check if device is knocked
在Swift5.1这一行:
manager.startDeviceMotionUpdatesToQueue(NSOperationQueue.mainQueue()) { [weak self] (data: CMDeviceMotion!, error: NSError!) in
需要:
manager.startDeviceMotionUpdates(to: .main) { [weak self] (data, error) in