Healthアプリによって報告されたユーザーの歩数と統合するSwift iOSアプリを作成しています。これを述語として使用して、過去1時間のユーザーの歩数を簡単に見つけることができます。
let anHourBeforeNow: NSDate = NSDate().dateByAddingTimeInterval(-60 * 60)
let predicate = HKQuery.predicateForSamplesWithStartDate(anHourBeforeNow, endDate: NSDate(), options: .None)
そして残りの部分は停止しているので、過去1時間のユーザーの歩数に正常にアクセスできます。 しかし、健康アプリがステップセクションに表示されるように、日が始まってからどのようにユーザーのステップデータにアクセスできますか?
私はこのようなことをしようとしています:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
let predicate = HKQuery.predicateForSamplesWithStartDate(newDate, endDate: NSDate(), options: .None)
ただし、このコードはタイムゾーンに合わせて調整されないため(ユーザーのいる日の始まりではなくUTCでその日の始まりがわかります)、ステップカウントが非常に大きくなります(理由は不明です)。
だから、ここに示すように、ヘルスで報告されたのと同じステップ数で、今日のユーザーのステップ数を取得するにはどうすればよいですか:
上記のコードの指示により、HKStatisticsCollectionQueryを使用する正しい方法を次に示します。
これはSwift 3で記述されているため、まだ3になっていない場合は、コードの一部を2.3または2に戻す必要があります。
Swift
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];
HKStatisticsCollectionQueryは、ある期間にわたってデータを取得するときに使用するのに適しています。特定の日付の手順を取得するには、HKStatisticsQueryを使用します。
Swift 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)
}
使用していたクエリは、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)
}
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)")
}
}
}
一定期間の毎日の合計ステップ数を取得する場合は、 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)
上記の回答を使用して、ここのAppleから: https://developer.Apple.com/reference/healthkit/hkstatisticsquery XcodeのSwift 2.3で動作するように以下を取得しました8.0。
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)
}