我正在使用HealthKit阅读用户的健康数据。尝试从健康数据中获取时区信息,以确定健康活动发生在哪个确切时区。为此,我依赖于' HKMetadataKeyTimeZone'来自HealthKit元数据的密钥。但是' HKMetadataKeyTimeZone'的价值即使对于Apple的Health应用程序自动记录的健康数据,密钥也始终为零。在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")
}
}