对于由苹果的健康应用程序 - HealthKit - iOS 创建的健康数据,HKMetadataKeyTimeZone 始终为零

问题描述 投票:0回答:2

我正在使用 HealthKit 读取用户的健康数据。尝试从健康数据中获取时区信息,以确定健康活动发生在哪个确切时区。为此,我依赖 HealthKit 元数据中的“HKMetadataKeyTimeZone”键。但即使对于苹果健康应用程序自动记录的健康数据,“HKMetadataKeyTimeZone”键的值也始终为零。在 Apple 的健康应用程序上手动输入的数据也存在同样的问题。

那么有没有其他键/方式可以给出每个样本的时区信息?

或者苹果的健康应用程序根本没有记录健康数据的时区信息?

或者苹果的健康应用程序正在记录健康数据的时区信息,而不是通过 HealthKit 框架将其提供给开发人员?

以下博客文章说,

samples retrieved from HealthKit do not have time zone information associated with them, unless the creating application captures that information in the metadata property using the predefined HKMetadataKeyTimeZone key.

Even Apple fails to add the time zone metadata to samples generated through their own Health app.

http://www.openmhealth.org/3-painful-lessons-learned-building-with-healthkit/


下面是我的代码:

import HealthKit

let healthKitStore: HKHealthStore = HKHealthStore()


func getHealthDataValue_QuantityType(healthQuantityType : HKQuantityType?, strUnitType : String)
{
  if let healthQuantityType = healthQuantityType {
    if (HKHealthStore.isHealthDataAvailable()) {

      let query = HKAnchoredObjectQuery(type: healthQuantityType, predicate: nil, anchor: nil, limit: Int(HKObjectQueryNoLimit)) { (query, newSamples, deletedSamples, newAnchor, error) -> Void in

        guard let samples = newSamples as? [HKQuantitySample] else {
          print("newSamples are nil, Error: \(error?.localizedDescription ?? "")\n, identifier: \(healthQuantityType.identifier)")
          return
        }

        var healthKitData = [[String: Any]]()

        for quantitySample in samples {
          let quantity = quantitySample.quantity
          let healthDataUnit : HKUnit

          if (strUnitType.characters.count > 0 ) {
            healthDataUnit = HKUnit(from: strUnitType)
          } else {
            healthDataUnit = HKUnit.count()
          }

          let tempActualhealthData = quantity.doubleValue(for: healthDataUnit)

          var dicHealth = [String: Any]()
          dicHealth["StartDate"] = quantitySample.startDate.epoch()
          dicHealth["EndDate"] = quantitySample.endDate.epoch()

          dicHealth["TimeZone"] = getTimeZoneString(sample: quantitySample)
          dicHealth["Value"] = tempActualhealthData
          dicHealth["Unit"] = strUnitType
          dicHealth["Source"] = quantitySample.sourceRevision.source.name
          dicHealth["WasUserEntered"] = quantitySample.metadata?["HKWasUserEntered"] as? Int

          healthKitData.append(dicHealth)
        }

        print(healthKitData)
      }

      healthKitStore.execute(query)
    }
  }
}

extension Date {
  func epoch(isMilliSeconds: Bool = false) -> UInt64 {
    return UInt64(self.timeIntervalSince1970 * (isMilliSeconds ? 1000 : 1))
  }
}

func getTimeZoneString(sample: HKSample? = nil, shouldReturnDefaultTimeZoneInExceptions: Bool = true) -> String? {
  var timeZone: TimeZone?
    print("sample?.metadata?[HKMetadataKeyTimeZone]: \(sample?.metadata?[HKMetadataKeyTimeZone])") // I have steps data recorded by my iPhone6s, not getting the timezone information for that health data.

  if let metaDataTimeZoneValue = sample?.metadata?[HKMetadataKeyTimeZone] as? String {
    timeZone = TimeZone(identifier: metaDataTimeZoneValue)
  }

  if shouldReturnDefaultTimeZoneInExceptions == true && timeZone == nil {
    timeZone = TimeZone.current
  }

  var timeZoneString: String?

  if let timeZone = timeZone {
    let seconds = timeZone.secondsFromGMT()

    let hours = seconds/3600
    let minutes = abs(seconds/60) % 60

    timeZoneString = String(format: "%+.2d:%.2d", hours, minutes)
  }

  return timeZoneString
}


var healthKitTypesToRead = Set<HKObjectType>()
if let stepCountObject = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount) {
  healthKitTypesToRead.insert(stepCountObject)
}

healthKitStore.requestAuthorization(toShare: nil, read: healthKitTypesToRead) { (success, error) in
  if error == nil {
    getHealthDataValue_QuantityType(healthQuantityType: HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount), strUnitType: "count")
  }
}
ios swift xcode healthkit hkhealthstore
2个回答
2
投票

没有什么不同的方法。如果您认为在健康应用程序中手动输入的数据应该有一个与之关联的时区,您应该向Apple提交错误


0
投票

这个问题困扰了我很多年,特别是自 2015 年 Apple Watch 推出以来,它记录到 Apple Health 的健康样本均不包含 HKMetadataKeyTimeZone 信息。

今天我发现了一个例外!原来Apple Watch记录的Sleep事件do设置了HKMetadataKeyTimeZone。

因此,解决方案是,无论您想要什么健康数据,您都可以对睡眠数据进行采样,然后对其进行搜索以查找样本中的时区变化。我不确定的一个问题是如何区分当地时间的变化,即。在英国,我们三月份从 GMT 转到 BST,然后在 10 月份返回 GMT。

无论如何,我希望以上内容对大家有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.