HealthKit Watch 应用程序未记录卡路里

Posted

技术标签:

【中文标题】HealthKit Watch 应用程序未记录卡路里【英文标题】:Calories not being recorded for HealthKit Watch app 【发布时间】:2016-08-13 22:53:41 【问题描述】:

我的应用中无法显示任何卡路里/activeEnergyBurned,不知道为什么?

WorkoutInterfaceController:

private func totalCalories() -> Double 
    return totalEnergyBurned.doubleValue(for: HKUnit.kilocalorie())


private func setTotalCalories(calories: Double) 
    totalEnergyBurned = HKQuantity(unit: HKUnit.kilocalorie(), doubleValue: calories)


func startQuery(quantityTypeIdentifier: HKQuantityTypeIdentifier) 
    let datePredicate = HKQuery.predicateForSamples(withStart: workoutStartDate, end: nil, options: .strictStartDate)
    let devicePredicate = HKQuery.predicateForObjects(from: [HKDevice.local()])
    let queryPredicate = NSCompoundPredicate(andPredicateWithSubpredicates:[datePredicate, devicePredicate])

    let updateHandler: ((HKAnchoredObjectQuery, [HKSample]?, [HKDeletedObject]?, HKQueryAnchor?, Error?) -> Void) =  query, samples, deletedObjects, queryAnchor, error in
        self.process(samples: samples, quantityTypeIdentifier: quantityTypeIdentifier)
    

    let query = HKAnchoredObjectQuery(type: HKObjectType.quantityType(forIdentifier: quantityTypeIdentifier)!,
                                      predicate: queryPredicate,
                                      anchor: nil,
                                      limit: HKObjectQueryNoLimit,
                                      resultsHandler: updateHandler)
    query.updateHandler = updateHandler
    healthStore.execute(query)

    activeDataQueries.append(query)


func process(samples: [HKSample]?, quantityTypeIdentifier: HKQuantityTypeIdentifier) 
    DispatchQueue.main.async  [weak self] in
        guard let strongSelf = self, !strongSelf.isPaused else  return 

        if let quantitySamples = samples as? [HKQuantitySample] 
            for sample in quantitySamples 
                if quantityTypeIdentifier == HKQuantityTypeIdentifier.activeEnergyBurned 
                    let newKCal = sample.quantity.doubleValue(for: HKUnit.kilocalorie())
                    strongSelf.setTotalCalories(calories: strongSelf.totalCalories() + newKCal)
                    print("NewKCal: \(newKCal)")
                    print("TotalCalories: \(strongSelf.totalCalories())")
                
            

            strongSelf.updateLabels()
        
    

无论我运行应用程序多长时间,日志都会打印出“0”。

我已经在模拟器和设备上进行了测试。

根据问题,这里是保存锻炼数据的代码

private func saveWorkout() 
    // Create and save a workout sample
    let configuration = workoutSession!.workoutConfiguration
    let isIndoor = (configuration.locationType == .indoor) as NSNumber
    print("locationType: \(configuration)")

    let workout = HKWorkout(activityType: configuration.activityType,
                            start: workoutStartDate!,
                            end: workoutEndDate!,
                            workoutEvents: workoutEvents,
                            totalEnergyBurned: totalEnergyBurned,
                            totalDistance: nil,
                            metadata: [HKMetadataKeyIndoorWorkout:isIndoor]);

    healthStore.save(workout)  success, _ in
        if success 
            self.addSamples(toWorkout: workout)
        
    

    // Pass the workout to Summary Interface Controller
    WKInterfaceController.reloadRootControllers(withNames: ["SummaryInterfaceController"], contexts: [workout])


private func addSamples(toWorkout workout: HKWorkout) 
    // Create energy and distance samples
    let totalEnergyBurnedSample = HKQuantitySample(type: HKQuantityType.activeEnergyBurned(),
                                                   quantity: totalEnergyBurned,
                                                   start: workoutStartDate!,
                                                   end: workoutEndDate!)


    // Add samples to workout
    healthStore.add([totalEnergyBurnedSample], to: workout)  (success: Bool, error: Error?) in
        if success 
            // Samples have been added
            print("Samples have been added")
        
    

【问题讨论】:

你保存在哪里? @Sandeep 我为如何保存数据添加了上面的代码。如果您有任何想法或需要我添加任何其他内容,请告诉我! 【参考方案1】:

您可以不使用谓词以另一种方式做到这一点。

weak var delegate: WorkoutSessionManagerDelegate?
let healthStore: HKHealthStore
var workoutSession: HKWorkoutSession 
var workoutStartDate: NSDate?
var workoutEndDate: NSDate?
var queries: [HKQuery] = []
var activeEnergySamples: [HKQuantitySample] = []
var distanceSamples: [HKQuantitySample] = []
var heartRateSamples: [HKQuantitySample] = []
let energyUnit = HKUnit.calorieUnit()
let distanceUnit = HKUnit.meterUnit()
let countPerMinuteUnit = HKUnit(fromString: "count/min")
var anchor = HKQueryAnchor(fromValue: Int(HKAnchoredObjectQueryNoAnchor))
let activeEnergyType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierActiveEnergyBurned)!
let heartRateType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)! // 1/3

var distanceType: HKQuantityType 
    if self.workoutSession.activityType == .Cycling 
        return HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceCycling)!
     else 
        return HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)!
    


var currentActiveEnergyQuantity: HKQuantity
var currentDistanceQuantity: HKQuantity
var currentHeartRateSample: HKQuantitySample? 

init(context: WorkoutSessionContext) 
    self.healthStore = context.healthStore
    self.workoutSession = HKWorkoutSession(activityType: context.activityType, locationType: context.locationType)
    self.currentActiveEnergyQuantity = HKQuantity(unit: self.energyUnit, doubleValue: 0.0)
    self.currentDistanceQuantity = HKQuantity(unit: self.distanceUnit, doubleValue: 0.0)

    super.init() 
    self.workoutSession.delegate = self


// MARK: Active Energy Burned Streaming
func createActiveEnergyStreamingQuery(workoutStartDate: NSDate) -> HKQuery? 

    print("Active energy query started")

    // ** Creating a match samples predicate to sum the data is no longer the convention **

    // Sum the new quantities with the current active energy quantity.
    guard let quantityType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierActiveEnergyBurned) else return nil

    // Instantiate a HKAnchoredObjectQuery object with a results handler that calls our sumEnergyBurnedSamples function
    let activeEnergyQuery = HKAnchoredObjectQuery(type: quantityType, predicate: nil, anchor: anchor, limit: Int(HKObjectQueryNoLimit))  (query, samples, deletedObjects, newAnchor, error) -> Void in
        guard let newAnchor = newAnchor else return
        self.anchor = newAnchor
        self.addActiveEnergySamples(samples)
    

    // Results handler that calls our addActiveEnergySamples function
    activeEnergyQuery.updateHandler = (query, samples, deletedObjects, newAnchor, error) -> Void in
            self.anchor = newAnchor!
            self.addActiveEnergySamples(samples)
    
    return activeEnergyQuery



func addActiveEnergySamples(samples: [HKSample]?) 

    print("Updating calorie samples")

    guard let activeEnergyBurnedSamples = samples as? [HKQuantitySample] else  return 

    // addActiveEnergySamples method dispatches back to the main queue
    dispatch_async(dispatch_get_main_queue())  

        // Adds the new active energy sample to the running total
      self.currentActiveEnergyQuantity = self.currentActiveEnergyQuantity.addQuantitiesFromSamples(activeEnergyBurnedSamples, unit: self.energyUnit)

        // Adds that sample to an array of samples accumulated over the workout
        self.activeEnergySamples += activeEnergyBurnedSamples

        // Whenever new samples become available, call the corresponding delegate method. This updates the UI with new samples.
        self.delegate?.workoutSessionManager(self, didUpdateActiveEnergyQuantity: self.currentActiveEnergyQuantity)

        // Print checks
        guard let sample = activeEnergyBurnedSamples.first elsereturn
        let value = sample.quantity.doubleValueForUnit(self.energyUnit)
        print(value)
    

【讨论】:

是的。我建议观看我正在观看的视频,以了解主类是如何完成初始化的。从大约 29 分钟开始。 developer.apple.com/videos/play/wwdc2015/203。他使用谓词,但您可以只替换为查询块。我自己的问题中也有很多代码。我将我的 init 添加到我的答案中。 你看 2016 年的视频了吗?他们在 2016 年的视频中的做法是不是更新了很多? 不确定我是否见过与您相同的一个,因为有很多。我的数据已成功打印到控制台。我只需要将数据发送到我的标签并确保我将数据存储到商店和其他详细信息,但主要部分已完成。工作量很大,我需要很多帮助。

以上是关于HealthKit Watch 应用程序未记录卡路里的主要内容,如果未能解决你的问题,请参考以下文章

如何在离线模式下从 Apple Watch 导入使用 HealthKit 的步骤?

如何在离线模式下从 Apple Watch 导入使用 HealthKit 的步骤?

如何通过 healthkit 使用 Apple Watch 心率更新 iOS 应用程序? (HealthKit 同步)

没有 iPhone 的 Apple Watch 上的 HealthKit 数据存储?

将 HealthKit 添加到 Apple Watch 扩展后,应用标识符冲突

将 HealthKit 添加到 Apple Watch 扩展后,应用标识符冲突