使用Swift计算HealthKit中的睡眠时间 [英] Calculate Asleep time in HealthKit using Swift

查看:159
本文介绍了使用Swift计算HealthKit中的睡眠时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码获取睡眠时间的总和.但是,它总在总结着睡眠和睡眠状态.我想得到的只是睡眠时间的总和.

I have the following code that gets the sum of sleep hours. However, it is summing inbed and asleep together. What I am trying to get is a sum for just the asleep time.

func readSleepAnalysis(date:Date){

func readSleepAnalysis(date: Date) {

    if let sleepType = HKObjectType.categoryType(forIdentifier: HKCategoryTypeIdentifier.sleepAnalysis) {

        let startDate = convertSleepStartDate(StartDate: date)
        let endDate = convertSleepEndDate(EndDate: date)
        let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictStartDate)

        let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)

        let query = HKSampleQuery(sampleType: sleepType, predicate: predicate, limit: 30, sortDescriptors: [sortDescriptor]) {
                                                    (query, samples, error) in

                                        guard
                                            error == nil,
                                        samples == samples as? [HKCategorySample] else {
                                                print("Something went wrong getting sleep analysis: \(String(describing: error))")
                                                return
                                        }

                                        let total = samples?.map(self.calculateSleepHours).reduce(0, {$0 + $1}) ?? 0
                                        DispatchQueue.main.async {
                                            self.userSleepMinutes = total
                                            print("userSleepHours = \(self.userSleepMinutes)")
                                        }

        }
        healthKit.execute(query)
    }
}

func calculateSleepHours(sample: HKSample) -> TimeInterval {

    let hours = sample.endDate.timeIntervalSince(sample.startDate) / 60 / 60

    return hours
}

我以前发现Apple记录所有基于UTC的数据.有道理!但是,这可能适用于有功电能和其他类似数据,但是无法像这样计算总睡眠时间.我正在计算当天下午05:59之前的晚上6点开始的总时间.这就是我的操作方式(可能有更好的方法,但此刻超出了我的范围).

I previously discovered that Apple records all data based on UTC. Make sense! However, this may work for active energy and other data like that but total sleep time can't be calculated like this. I am calculating the total time from 6 PM the night prior to 05:59 AM that day. Here is how I am doing that (there may be a better way but it's beyond me at this moment).

func convertSleepStartDate(StartDate: Date) -> Date {

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyy-MM-dd '18':'00':'01' +0000"
    let dateString = dateFormatter.string(from: StartDate)
    dateFormatter.dateFormat = "yyy-MM-dd HH:mm:ss +0000"
    let date = dateFormatter.date(from: dateString)
    let datePrior = Calendar.current.date(byAdding: .hour, value: -24, to: date!)
    print(datePrior as Any)

    return datePrior!
}

func convertSleepEndDate(EndDate: Date) -> Date {

    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyy-MM-dd '17':'59':'59' +0000"
    let dateString = dateFormatter.string(from: EndDate)
    dateFormatter.dateFormat = "yyy-MM-dd HH:mm:ss +0000"
    let date = dateFormatter.date(from: dateString)
    print(date as Any)

    return date!
}

有什么想法吗?

推荐答案

迟到总比没有好:在您的calculateSleepHours函数中,应对照HKCategoryValueSleepAnalysis常量(inBed,睡眠,唤醒)检查sample.value.这将告诉您间隔的类型.它还将教您Apple如何测量和返回此数据.请注意时间间隔,因为当您在手表上计划的睡眠时间结束时,它将为您提供inBed时间的摘要.

Better late than never: In your calculateSleepHours function, you should check sample.value against the HKCategoryValueSleepAnalysis constants (inBed, asleep, awake). That will tell you the interval's type. It will also teach you how Apple measures and returns this data. Keep an eye on the intervals, because when you hit the end of the planned sleep time on the watch, it will give you a summary of inBed time.

let value1 = (sample.value == HKCategoryValueSleepAnalysis.inBed.rawValue) ? "InBed" : "Asleep"
                    let value2 = (sample.value == HKCategoryValueSleepAnalysis.asleep.rawValue) ? "Asleep" : "Awake"
                    let value3 = (sample.value == HKCategoryValueSleepAnalysis.awake.rawValue) ? "Awake" : "Asleep"

这3个值包含每个间隔正在测量的常数的类型.它几乎总是处于睡眠状态,但可能会因Watch OS版本而有所不同.

The 3 values contain the type of constant that each interval is measuring. It is almost always asleep, but may differ depending on the Watch OS versions.

您可以打印这些值,并在每个时间间隔的基础上查看正在测量的内容.确保也打印sample.startDate和sample.endDate.这样可以教您所有需要知道的两个日期之间的实际睡眠时间.

You can print the values and see, on a per interval basis, exactly what is being measured. Be sure to print the sample.startDate and sample.endDate too. That will teach you all you need to know to get actual sleep time between two Dates.

这篇关于使用Swift计算HealthKit中的睡眠时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆