HKCategoryValueSleepAnalysis Sending incorrect sleep data.

The edited code still has the problem of not lining up with the health app

    private func fetchSleepData(for date: Date) {
        let sleepType = HKObjectType.categoryType(forIdentifier: .sleepAnalysis)!
        
        let endOfPeriod = date
        let startOfPeriod = Calendar.current.date(byAdding: .day, value: -1, to: endOfPeriod)!
        
        let predicate = HKQuery.predicateForSamples(withStart: startOfPeriod, end: endOfPeriod, options: [.strictStartDate, .strictEndDate])
        
        let query = HKSampleQuery(sampleType: sleepType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { query, samples, error in
            guard let samples = samples as? [HKCategorySample], !samples.isEmpty else {
                DispatchQueue.main.async {
                    self.inBedTime = 0
                    self.coreTime = 0
                    self.deepTime = 0
                    self.remTime = 0
                    self.isSleepDataAvailable = false
                }
                print("No sleep data available for date: \(date)")
                return
            }

            print("Fetched \(samples.count) sleep samples for date: \(date)")

            var inBedTime = 0.0
            var asleepTime = 0.0
            var deepTime = 0.0
            var remTime = 0.0

            for sample in samples {
                print("Sample value: \(sample.value)")
                let duration = sample.endDate.timeIntervalSince(sample.startDate) / 60 // convert to minutes
                switch sample.value {
                case HKCategoryValueSleepAnalysis.inBed.rawValue:
                    inBedTime += duration
                case HKCategoryValueSleepAnalysis.asleepCore.rawValue:
                    coreTime += duration
                case HKCategoryValueSleepAnalysis.asleepDeep.rawValue:
                    deepTime += duration
                case HKCategoryValueSleepAnalysis.asleepREM.rawValue:
                    remTime += duration
                default:
                    break
                }
            }
            
            DispatchQueue.main.async {
                self.inBedTime = inBedTime
                self.coreTime = coreTime
                self.deepTime = deepTime
                self.remTime = remTime
                self.isSleepDataAvailable = true
            }
        }

        healthStore?.execute(query)
    }

Replies

Do any of the samples overlap? If so you'll be counting too much. Are any of the samples logged as asleepUnspecified? If so, you've forgotten to count them. It's also not clear what date you're passing in to start looking back from. You're just fetching the last 24 hours but the dates in the Health app are based from 6pm-6pm.

  • i Don’t believe the issue is with overlap as it’s undercounting the data for the time periods. I don’t understand the 6pm/6pm thing. This code checks a json file that has a date and is displaying any sleep data from the past 24 hours (the other parts I have not included as they work as intende.)

  • It's under reporting the time in my case (by a few minuets). I don't understand the 6-6 thing? this code gets a time from the file via the date call, it's checking for all sleep time in the last 24 hours as to support those with a daytime sleep schedule.

    I posted this because my last response wasn't appearing on reloads, apologies.

  • The charts in the app don't reflect an arbitrary 24 hour period. It tries to reflect "how much did you sleep last night" where that period of time is generally a 24 hour bucket from 6pm - 6pm the next day.

Add a Comment