WatchOS 6.0, Swift 5.0: без фоновой тактики - PullRequest
0 голосов
/ 10 марта 2020

Я пытаюсь получить отзыв c, когда приложение находится в фоновом режиме. По существу, когда определенное значение превышает пороговое значение, должна быть обратная связь c. Из того, что я вижу, у меня все настроено правильно; функция, которую я вызываю, когда превышен порог, который, как я знаю, вызывается, потому что я вижу это в журнале, но нет звука или вибрации. Поэтому я не уверен, что я делаю неправильно. Он отлично работает, когда приложение отображается на экране, но не в фоновом режиме.

Используется более старый образец кода Apple (я знаю об устаревших элементах). Моя конечная цель - создать приложение для анализа бейсбольной качки, а тактильные средства - укрепить мышечную память, что-то вроде тренировки с кликером у собак.

Вот MotionManager, который загружает CoreMotion.

import Foundation
import CoreMotion
import WatchKit
import os.log

protocol MotionManagerDelegate: class {
    func didUpdateMotion(_ manager: MotionManager, gravityStr: String, rotationRateStr: String, userAccelStr: String, attitudeStr: String, rollInt: Double)
}

extension Date {
    var millisecondsSince1970:Int64 {
        return Int64((self.timeIntervalSince1970 * 1000.0).rounded())
    }
}

class MotionManager {
// MARK: Properties

let motionManager = CMMotionManager()
let queue = OperationQueue()
let wristLocationIsLeft = WKInterfaceDevice.current().wristLocation == .left

// MARK: Application Specific Constants

// The app is using 50hz data and the buffer is going to hold 1s worth of data.
let sampleInterval = 1.0 / 50
let rateAlongGravityBuffer = RunningBuffer(size: 50)

weak var delegate: MotionManagerDelegate?

var gravityStr = ""
var rotationRateStr = ""
var userAccelStr = ""
var attitudeStr = ""
var rollInt = 0.0

var recentDetection = false

// MARK: Initialization

init() {
    // Serial queue for sample handling and calculations.
    queue.maxConcurrentOperationCount = 1
    queue.name = "MotionManagerQueue"
}

// MARK: Motion Manager

func startUpdates() {
    if !motionManager.isDeviceMotionAvailable {
        print("Device Motion is not available.")
        return
    }

    os_log("Start Updates");

    motionManager.deviceMotionUpdateInterval = sampleInterval
    motionManager.startDeviceMotionUpdates(to: queue) { (deviceMotion: CMDeviceMotion?, error: Error?) in
        if error != nil {
            print("Encountered error: \(error!)")
        }

        if deviceMotion != nil {
            self.processDeviceMotion(deviceMotion!)
        }
    }
}

func stopUpdates() {
    if motionManager.isDeviceMotionAvailable {
        motionManager.stopDeviceMotionUpdates()
    }
}

// MARK: Motion Processing

func processDeviceMotion(_ deviceMotion: CMDeviceMotion) {
    gravityStr = String(format: "X: %.1f Y: %.1f Z: %.1f" ,
                        deviceMotion.gravity.x,
                        deviceMotion.gravity.y,
                        deviceMotion.gravity.z)
    userAccelStr = String(format: "X: %.1f Y: %.1f Z: %.1f" ,
                       deviceMotion.userAcceleration.x,
                       deviceMotion.userAcceleration.y,
                       deviceMotion.userAcceleration.z)
    rotationRateStr = String(format: "X: %.1f Y: %.1f Z: %.1f" ,
                          deviceMotion.rotationRate.x,
                          deviceMotion.rotationRate.y,
                          deviceMotion.rotationRate.z)
    attitudeStr = String(format: "r: %.1f p: %.1f y: %.1f" ,
                             deviceMotion.attitude.roll,
                             deviceMotion.attitude.pitch,
                             deviceMotion.attitude.yaw)

    rollInt = deviceMotion.attitude.roll

    let timestamp = Date().millisecondsSince1970

    os_log("Motion: %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@, %@",
           String(timestamp),
           String(deviceMotion.gravity.x),
           String(deviceMotion.gravity.y),
           String(deviceMotion.gravity.z),
           String(deviceMotion.userAcceleration.x),
           String(deviceMotion.userAcceleration.y),
           String(deviceMotion.userAcceleration.z),
           String(deviceMotion.rotationRate.x),
           String(deviceMotion.rotationRate.y),
           String(deviceMotion.rotationRate.z),
           String(deviceMotion.attitude.roll),
           String(deviceMotion.attitude.pitch),
           String(deviceMotion.attitude.yaw))

    updateMetricsDelegate();
}

// MARK: Data and Delegate Management

func updateMetricsDelegate() {
    delegate?.didUpdateMotion(self,gravityStr:gravityStr, rotationRateStr: rotationRateStr, userAccelStr: userAccelStr, attitudeStr: attitudeStr, rollInt: rollInt)
}
}

Вот мой WorkOutMangager, где контролируется сеанс тренировки. Функция, которую я вызываю, находится в самом конце. Это получение значений из MotionManagerDelagate.

import Foundation
import HealthKit
import WatchKit
import os.log

protocol WorkoutManagerDelegate: class {
    func didUpdateMotion(_ manager: WorkoutManager, gravityStr: String, rotationRateStr: String, userAccelStr: String, attitudeStr: String)
}

class WorkoutManager: MotionManagerDelegate {
    // MARK: Properties
    let motionManager = MotionManager()
    let healthStore = HKHealthStore()

var rollInt = 0.0

weak var delegate: WorkoutManagerDelegate?
var session: HKWorkoutSession?

// MARK: Initialization

init() {
    motionManager.delegate = self
}

// MARK: WorkoutManager

func startWorkout() {
    // If we have already started the workout, then do nothing.
    if (session != nil) {
        return
    }

    // Configure the workout session.
    let workoutConfiguration = HKWorkoutConfiguration()
    workoutConfiguration.activityType = .tennis
    workoutConfiguration.locationType = .outdoor

    do {
        session = try HKWorkoutSession(configuration: workoutConfiguration)
    } catch {
        fatalError("Unable to create the workout session!")
    }

    // Start the workout session andKAKAHA.watchWatch.watchkitapp device motion updates.
    healthStore.start(session!)
    motionManager.startUpdates()

    if(rollInt < -0.9){
        WKInterfaceDevice.current().play(.failure)
        os_log("ALERT!!!")
    }
}

func stopWorkout() {
    // If we have already stopped the workout, then do nothing.
    if (session == nil) {
        return
    }

    // Stop the device motion updates and workout session.
    motionManager.stopUpdates()
    healthStore.end(session!)

    // Clear the workout session.
    session = nil
}

// MARK: MotionManagerDelegate

func didUpdateMotion(_ manager: MotionManager, gravityStr: String, rotationRateStr: String, userAccelStr: String, attitudeStr: String, rollInt: Double) {

    delegate?.didUpdateMotion(self, gravityStr: gravityStr, rotationRateStr: rotationRateStr, userAccelStr: userAccelStr, attitudeStr: attitudeStr)

    self.rollInt = rollInt
    rollAlert()
}

@objc fileprivate func rollAlert(){
    if (rollInt < -0.9) {
        WKInterfaceDevice.current().play(.failure)
        os_log("TOO CLOSE TO FACE!!!")
    }
   }
}

1 Ответ

0 голосов
/ 10 марта 2020

Я чувствую себя глупо. У меня не было звука в качестве фонового режима.

...