HKMetadataKeyTimeZone 对于由苹果的 Health App - HealthKit - iOS 创建的健康数据始终为零

Posted

技术标签:

【中文标题】HKMetadataKeyTimeZone 对于由苹果的 Health App - HealthKit - iOS 创建的健康数据始终为零【英文标题】:HKMetadataKeyTimeZone is always nil for health data which is created by apple's Health App - HealthKit - iOS 【发布时间】:2018-03-13 07:57:52 【问题描述】:

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

那么有没有其他键/方式可以为每个样本提供时区信息?

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

或者 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")
  

【问题讨论】:

嗨@Ashok,你有这个的objc副本吗? @david,不幸的是,我没有 objc 副本,因为我只是在做一个 swift 项目。 【参考方案1】:

没有不同的方法。如果您认为在“健康”应用中手动输入的数据应该有一个与之关联的时区,您应该 file a bug with Apple。

【讨论】:

好的。不仅是手动输入的数据,即使是 iPhone 自动记录的健康数据,比如 Steps,也无法获取时区信息。

以上是关于HKMetadataKeyTimeZone 对于由苹果的 Health App - HealthKit - iOS 创建的健康数据始终为零的主要内容,如果未能解决你的问题,请参考以下文章

为啥 iOS 会显示警告“此应用程序需要由开发人员更新才能在此版本的 iOS 上运行”。对于我的反应原生应用程序?

15 文章 6.8万 总阅读 查看TA的文章> 0 分享到 对于IT这两个字眼,是不是只能由学习过

15 文章 6.8万 总阅读 查看TA的文章> 0 分享到 对于IT这两个字眼,是不是只能由学习过

由移动端级联选择器所引发的对于数据结构的思考

堆和栈的主要区别由以下几点:

对于仅由其他Web服务使用的Web API,建议的身份验证类型是什么