HealthKit Swift 获取今天的步骤
Posted
技术标签:
【中文标题】HealthKit Swift 获取今天的步骤【英文标题】:HealthKit Swift getting today's steps 【发布时间】:2016-04-11 21:29:11 【问题描述】:我正在制作一个快速的 ios 应用程序,该应用程序与 Health 应用程序报告的用户步数相集成。我可以很容易地找到用户在过去一小时内的步数,以此作为我的谓词:
let anHourBeforeNow: NSDate = NSDate().dateByAddingTimeInterval(-60 * 60)
let predicate = HKQuery.predicateForSamplesWithStartDate(anHourBeforeNow, endDate: NSDate(), options: .None)
剩下的我已经准备好了,所以我可以成功地访问用户最后一小时的步数。 但我如何才能访问用户从一天开始以来的步数数据,例如步数部分中显示的健康应用程序?
我正在尝试做这样的事情:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None)
但是这段代码没有针对时区进行调整(所以它给了我 UTC 的一天的开始,而不是用户所在的一天的开始)而且我的步数也被高度夸大了(原因未知) .
那么我怎样才能获得用户当天的步数,与健康中报告的步数相同,如下图所示:
【问题讨论】:
这可以帮助您快速查看答案***.com/questions/29582462/… 您应该包含查询代码以及如何计算步数,以便我们帮助您解决此问题。如果您发现您犯了同样的错误,您也可以关注我对***.com/questions/36560367/… 的回复以获得指导。 NSTimeZone.localTimeZone() 在你的应用中返回什么? 答案可以在这里找到:***.com/questions/36560367/… 【参考方案1】:HKStatisticsCollectionQuery 更适合在您想要检索一段时间内的数据时使用。使用 HKStatisticsQuery 获取特定日期的步骤。
斯威夫特 5:
let healthStore = HKHealthStore()
func getTodaysSteps(completion: @escaping (Double) -> Void)
let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
let now = Date()
let startOfDay = Calendar.current.startOfDay(for: now)
let predicate = HKQuery.predicateForSamples(
withStart: startOfDay,
end: now,
options: .strictStartDate
)
let query = HKStatisticsQuery(
quantityType: stepsQuantityType,
quantitySamplePredicate: predicate,
options: .cumulativeSum
) _, result, _ in
guard let result = result, let sum = result.sumQuantity() else
completion(0.0)
return
completion(sum.doubleValue(for: HKUnit.count()))
healthStore.execute(query)
【讨论】:
这个方案比公认的方案更简单、更高效。 @Jose 你能回答这个***.com/questions/50620547/… 当然,我发布了一个例子。 我们可以分别计算跑步和步行的步数吗? @PrashantTukadiya 是的,你只需要使用不同的数量类型。【参考方案2】:根据上述代码的指示,这是使用 HKStatisticsCollectionQuery 的正确方法。
这是用 Swift 3 编写的,因此您可能需要将一些代码转换回 2.3 或 2(如果尚未在 3 上)。
斯威夫特 3
func retrieveStepCount(completion: (stepRetrieved: Double) -> Void)
// Define the Step Quantity Type
let stepsCount = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)
// Get the start of the day
let date = Date()
let cal = Calendar(identifier: Calendar.Identifier.gregorian)
let newDate = cal.startOfDay(for: date)
// Set the Predicates & Interval
let predicate = HKQuery.predicateForSamples(withStart: newDate, end: Date(), options: .strictStartDate)
var interval = DateComponents()
interval.day = 1
// Perform the Query
let query = HKStatisticsCollectionQuery(quantityType: stepsCount!, quantitySamplePredicate: predicate, options: [.cumulativeSum], anchorDate: newDate as Date, intervalComponents:interval)
query.initialResultsHandler = query, results, error in
if error != nil
// Something went Wrong
return
if let myResults = results
myResults.enumerateStatistics(from: self.yesterday, to: self.today)
statistics, stop in
if let quantity = statistics.sumQuantity()
let steps = quantity.doubleValue(for: HKUnit.count())
print("Steps = \(steps)")
completion(stepRetrieved: steps)
storage.execute(query)
Objective-C
HKQuantityType *type = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
NSDate *today = [NSDate date];
NSDate *startOfDay = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian] startOfDayForDate:today];
NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startOfDay endDate:today options:HKQueryOptionStrictStartDate];
NSDateComponents *interval = [[NSDateComponents alloc] init];
interval.day = 1;
HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:type quantitySamplePredicate:predicate options:HKStatisticsOptionCumulativeSum anchorDate:startOfDay intervalComponents:interval];
query.initialResultsHandler = ^(HKStatisticsCollectionQuery * _Nonnull query, HKStatisticsCollection * _Nullable result, NSError * _Nullable error)
if (error != nil)
// TODO
else
[result enumerateStatisticsFromDate:startOfDay toDate:today withBlock:^(HKStatistics * _Nonnull result, BOOL * _Nonnull stop)
HKQuantity *quantity = [result sumQuantity];
double steps = [quantity doubleValueForUnit:[HKUnit countUnit]];
NSLog(@"Steps : %f", steps);
];
;
[self.storage executeQuery:query];
【讨论】:
@Gugulethu 你能指导我如何截断手动添加的步骤吗? @Byte 只是想了解您的问题 - 您想截断从 HealthKit 以外的其他来源手动添加的步骤? 不,我想获取 iphone 检测到的所有步骤,并由其他跟踪器自动添加。但我不希望用户手动添加到健康应用程序中的那些步骤。 我还真不知道该怎么做!会做一些研究并尽快回复您。 self.yesterday 和 self.today 来自哪里?【参考方案3】:对于 swift 4.2
1) 获取 HealthKitPermission
import HealthKit
func getHealthKitPermission()
delay(0.1)
guard HKHealthStore.isHealthDataAvailable() else
return
let stepsCount = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
self.healthkitStore.requestAuthorization(toShare: [], read: [stepsCount]) (success, error) in
if success
print("Permission accept.")
else
if error != nil
print(error ?? "")
print("Permission denied.")
2) 获取特定日期的步数
func getStepsCount(forSpecificDate:Date, completion: @escaping (Double) -> Void)
let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!
let (start, end) = self.getWholeDate(date: forSpecificDate)
let predicate = HKQuery.predicateForSamples(withStart: start, end: end, options: .strictStartDate)
let query = HKStatisticsQuery(quantityType: stepsQuantityType, quantitySamplePredicate: predicate, options: .cumulativeSum) _, result, _ in
guard let result = result, let sum = result.sumQuantity() else
completion(0.0)
return
completion(sum.doubleValue(for: HKUnit.count()))
self.healthKitStore.execute(query)
func getWholeDate(date : Date) -> (startDate:Date, endDate: Date)
var startDate = date
var length = TimeInterval()
_ = Calendar.current.dateInterval(of: .day, start: &startDate, interval: &length, for: startDate)
let endDate:Date = startDate.addingTimeInterval(length)
return (startDate,endDate)
如何使用
self.getStepsCount(forSpecificDate: Date()) (steps) in
if steps == 0.0
print("steps :: \(steps)")
else
DispatchQueue.main.async
print("steps :: \(steps)")
【讨论】:
【参考方案4】:如果您想获取一段时间内每天的总步数,请使用HKStatisticsCollectionQuery,Swift 4.2 中的代码
let startDate = Date().addingTimeInterval(-3600 * 24 * 7)
let endDate = Date()
let predicate = HKQuery.predicateForSamples(
withStart: startDate,
end: endDate,
options: [.strictStartDate, .strictEndDate]
)
// interval is 1 day
var interval = DateComponents()
interval.day = 1
// start from midnight
let calendar = Calendar.current
let anchorDate = calendar.date(bySettingHour: 12, minute: 0, second: 0, of: Date())
let query = HKStatisticsCollectionQuery(
quantityType: HKSampleType.quantityType(forIdentifier: .stepCount)!,
quantitySamplePredicate: predicate,
options: .cumulativeSum,
anchorDate: anchorDate!,
intervalComponents: interval
)
query.initialResultsHandler = query, results, error in
guard let results = results else
return
results.enumerateStatistics(
from: startDate,
to: endDate,
with: (result, stop) in
let totalStepForADay = result.sumQuantity()?.doubleValue(for: HKUnit.count()) ?? 0
)
store.execute(query)
【讨论】:
【参考方案5】:您使用的查询从 Healthkit 获取用户记录的所有步骤,而不是对 Health 应用执行的重复步骤进行智能过滤。相反,您希望获取 Health 应用程序在组合不同来源的步数后生成的聚合步数数据,以获得准确的计数。
为此,您可以使用以下代码:
func recentSteps2(completion: (Double, NSError?) -> () )
// this function gives you all of the steps the user has taken since the beginning of the current day.
checkAuthorization() // checkAuthorization just makes sure user is allowing us to access their health data.
let type = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount) // The type of data we are requesting
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None) // Our search predicate which will fetch all steps taken today
// The actual HealthKit Query which will fetch all of the steps and add them up for us.
let query = HKSampleQuery(sampleType: type!, predicate: predicate, limit: 0, sortDescriptors: nil) query, results, error in
var steps: Double = 0
if results?.count > 0
for result in results as! [HKQuantitySample]
steps += result.quantity.doubleValueForUnit(HKUnit.countUnit())
completion(steps, error)
storage.executeQuery(query)
【讨论】:
抱歉,这是不正确的。 HKSampleQuery 返回每一步记录(它不会删除重复项),并且是一种计算与谓词匹配的样本总和的低效方法。您应该使用 HKStatisticsQuery。【参考方案6】:在此处使用上述答案和来自 Apple 的答案:https://developer.apple.com/reference/healthkit/hkstatisticsquery 我得到以下在 Xcode 8.0 上的 swift 2.3 中工作。
class func getStepCountHealth(startDate: NSDate, endDate: NSDate, completion:(Double?, NSError?)->())
let healthKitStore:HKHealthStore = HKHealthStore()
// Define the sample type
let sampleType = HKQuantityType.quantityTypeForIdentifier(
HKQuantityTypeIdentifierStepCount)
// Set the predicate
let predicate = HKQuery.predicateForSamplesWithStartDate(startDate,
endDate: endDate, options: .None)
// build the query
let sampleQuery = HKStatisticsQuery(quantityType: sampleType!,
quantitySamplePredicate: predicate,
options: .CumulativeSum) query, results, error in
if results != nil
let quantity = results?.sumQuantity()
let unit = HKUnit.countUnit()
let totalSteps = quantity?.doubleValueForUnit(unit)
completion(totalSteps, error)
// print("totalSteps for \(endDate) are \(totalSteps!)")
else
completion(nil, error)
// print("results are nil")
return
// execute the Query
healthKitStore.executeQuery(sampleQuery)
【讨论】:
以上是关于HealthKit Swift 获取今天的步骤的主要内容,如果未能解决你的问题,请参考以下文章
如何在 swift 3 中获取和更新 Healthkit 中的高度?