ios - 如何使用 Apple HealthKit 获得每日 sleep 时长?

标签 ios healthkit

我正在做一个从 Apple HealthKit 读取每日步数和 sleep 数据的应用程序。

对于 步骤 ,这很容易,因为它是 HKQuantityType ,所以我可以在其上应用 HKStatisticsOptionCumulativeSum 选项。输入开始日期、结束日期和日期间隔,你就明白了。

- (void)readDailyStepsSince:(NSDate *)date completion:(void (^)(NSArray *results, NSError *error))completion {
    NSDate *today = [NSDate date];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *comps = [calendar components:NSCalendarUnitDay|NSCalendarUnitMonth|NSCalendarUnitYear fromDate:date];
    comps.hour = 0;
    comps.minute = 0;
    comps.second = 0;

    NSDate *midnightOfStartDate = [calendar dateFromComponents:comps];
    NSDate *anchorDate = midnightOfStartDate;

    HKQuantityType *stepType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    HKStatisticsOptions sumOptions = HKStatisticsOptionCumulativeSum;
    NSPredicate *dateRangePred = [HKQuery predicateForSamplesWithStartDate:midnightOfStartDate endDate:today options:HKQueryOptionNone];

    NSDateComponents *interval = [[NSDateComponents alloc] init];
    interval.day = 1;
    HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:stepType quantitySamplePredicate:dateRangePred options:sumOptions anchorDate:anchorDate intervalComponents:interval];

    query.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *result, NSError *error) {

        NSMutableArray *output = [NSMutableArray array];

        // we want "populated" statistics only, so we use result.statistics to iterate
        for (HKStatistics *sample in result.statistics) {
            double steps = [sample.sumQuantity doubleValueForUnit:[HKUnit countUnit]];
            NSDictionary *dict = @{@"date": sample.startDate, @"steps": @(steps)};
            //NSLog(@"[STEP] date:%@ steps:%.0f", s.startDate, steps);
            [output addObject:dict];
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            if (completion != nil) {
                NSLog(@"[STEP] %@", output);
                completion(output, error);
            }
        });
    };

    [self.healthStore executeQuery:query];
}

但是对于 Sleep 来说并不是那么简单。我坚持了很多事情。
  • 首先,与步骤不同, sleep 是一个 HKCategoryType 。所以我们不能使用 HKStatisticsCollectionQuery 来求和,因为这个方法只接受 HKQuantityType
  • 还有 2 种 sleep 值类型,HKCategoryValueSleepAnalysisInBedHKCategoryValueSleepAnalysisAsleep。我不确定哪个值最适合 sleep 持续时间。为简单起见,我将仅使用 HKCategoryValueSleepAnalysisAsleep
  • sleep 数据来自 HKCategorySample 对象数组。每个都有开始日期和结束日期。我如何有效地结合这些数据,将其修剪到一天内,并从中获得每日 sleep 时间(以分钟为单位)?我在 DateTool pod 中发现了这个 DTTimePeriodCollection 类,它可以完成这项工作,但我还没有弄清楚。

  • 简单地说,如果有人知道如何使用 Apple HealthKit 获得每日 sleep 时长,请告诉我!

    最佳答案

    检查我是如何做到这一点的,它对我有用以收集 sleep 数据

    func sleepTime() {
            let healthStore = HKHealthStore()
            // startDate and endDate are NSDate objects
            // first, we define the object type we want
            if let sleepType = HKObjectType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis) {
                // You may want to use a predicate to filter the data... startDate and endDate are NSDate objects corresponding to the time range that you want to retrieve
                //let predicate = HKQuery.predicateForSamplesWithStartDate(startDate,endDate: endDate ,options: .None)
                // Get the recent data first
                let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
                // the block completion to execute
                let query = HKSampleQuery(sampleType: sleepType, predicate: nil, limit: 100000, sortDescriptors: [sortDescriptor]) { (query, tmpResult, error) -> Void in
                    if error != nil {
                        // Handle the error in your app gracefully
                        return
                    }
                    if let result = tmpResult {
                       for item in result {
                            if let sample = item as? HKCategorySample {
                                   let startDate = sample.startDate
                                   let endDate = sample.endDate
                                   print()
                                 let sleepTimeForOneDay = sample.endDate.timeIntervalSince(sample.startDate)
                            }
                        }
                    }
              }
        }
    

    这给出了入口槽的数组。

    关于ios - 如何使用 Apple HealthKit 获得每日 sleep 时长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30702100/

    相关文章:

    ios - 为什么 UITextField.text 是可选的?

    ios - 无法理解代码中没有相关方法的崩溃报告

    ios - 我可以在 Apple Watch 上同时开始 2 个锻炼类(class)吗?

    快速错误 "cannot assign value of type ' 接口(interface) Controller '键入 HKWorkoutSessionDelegate'

    ios - 由于未捕获的异常 '_HKObjectValidationFailureException' 而终止应用程序

    c++ - Boost、Lib C++ 和 Xcode

    ios - 将 ScrollView 与 Array 一起使用时出现问题

    ios - 如何在异步线程中更新 ProgressView

    ios - 如何从临床健康记录实例获取医疗机构?

    swift - 数量类型(标识符 :) deprecated in a future version of iOS?