Получайте данные bodyMass за последние 30 дней из HealthKit с помощью Swift - PullRequest
0 голосов
/ 25 июня 2019

Я изучаю Swift и HealthKit прямо сейчас и немного застрял в получении данных.Я уже успешно запросил свой dietaryCaloriesConsumed за последние 30 дней, который выводится на консоль.

Когда я пытаюсь сделать то же самое с данными веса, я не получаю вывод.Хотя я могу получить данные о весе за определенную дату, считая дату назад и используя только первый образец.

Мой код прямо сейчас:

    func getWeightData2(forDay days: Int, completion: @escaping ((_ weight: Double?, _ date: Date?) -> Void)) {
    // Getting quantityType as stepCount
    guard let weight = HKObjectType.quantityType(forIdentifier: .bodyMass) else {
        print("*** Unable to create a step count type ***")
        return
    }

    let now = Date()
    let startDate = Calendar.current.date(byAdding: DateComponents(day: -days), to: now)!

    var interval = DateComponents()
    interval.day = 1

    var anchorComponents = Calendar.current.dateComponents([.day, .month, .year], from: now)
    anchorComponents.hour = 0
    let anchorDate = Calendar.current.date(from: anchorComponents)!

    let query = HKStatisticsCollectionQuery(quantityType: weight,
                                            quantitySamplePredicate: nil,
                                            options: [.mostRecent],
                                            anchorDate: anchorDate,
                                            intervalComponents: interval)
    query.initialResultsHandler = { _, results, error in
        guard let results = results else {
            print("ERROR")
            return
        }

        results.enumerateStatistics(from: startDate, to: now) { statistics, _ in
            if let sum = statistics.sumQuantity() {
                let weight = Int(sum.doubleValue(for: HKUnit.gramUnit(with: .kilo)).roundToDecimal(2))
                                  print("Weight Tracked: \(weight), on date: \(statistics.endDate)")
                //                    completion(calories, statistics.endDate)
                return
            }
        }
        completion(nil, nil)
    }
    healthStore.execute(query)
}

С этим я не делаю 'не получить никакого выхода.С небольшими изменениями для dietaryCaloriesConsumed я получаю калории на 30 дней, суммируемые за каждый день (с опцией cumulativeSum)

Что на самом деле делает работа, так это получение данных за определенный день, например:

    func getWeightData(forDay days: Int) {
    let quantityType: HKQuantityType = HKQuantityType.quantityType(forIdentifier: .bodyMass)!

    // fetch last 30 days
    let startDate = Date.init(timeIntervalSinceNow: TimeInterval(-days*24*60*60))
    let endDate = Date()
    let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate)

    let sampleQuery = HKSampleQuery.init(sampleType: quantityType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { (query, samples, error) in
        DispatchQueue.main.async {
            guard let samples = samples else { return }
            let mostRecentSample = samples.first as? HKQuantitySample
            let bodyMass = mostRecentSample?.quantity.doubleValue(for: HKUnit.gramUnit(with: .kilo)).roundToDecimal(2)
            print("Weight tracked: \(bodyMass) on date: \(endDate)")
    }
    }
    healthStore.execute(sampleQuery)
}

Из моего ViewController я вызываю эти функции следующим образом:

profileStore.getTotalCalories(forDay: 30) {_,_   in
    }

и

profileStore.getWeightData(forDay: 30)

Это работает, но я уверен, что есть много места для утверждения.

Есть идеи, что я делаю не так с моим первым кодом?Каков наилучший способ получить n дней dietaryCaloriesConsumed или bodyMass для дальнейшей обработки?

Большое спасибо:)

1 Ответ

0 голосов
/ 26 июня 2019

Я только что решил свою собственную проблему:

    func getWeightData(forDay days: Int, completion: @escaping ((_ weight: Double?, _ date: Date?) -> Void)) {
    // Getting quantityType as stepCount
    guard let bodyMassType = HKObjectType.quantityType(forIdentifier: .bodyMass) else {
        print("*** Unable to create a bodyMass type ***")
        return
    }

    let now = Date()
    let startDate = Calendar.current.date(byAdding: DateComponents(day: -days), to: now)!

    var interval = DateComponents()
    interval.day = 1

    var anchorComponents = Calendar.current.dateComponents([.day, .month, .year], from: now)
    anchorComponents.hour = 0
    let anchorDate = Calendar.current.date(from: anchorComponents)!

    // Note to myself:: StatisticsQuery!! Nicht Collection! Option .mostRecent. Achtung, unten auch setzen!!
    let query = HKStatisticsCollectionQuery(quantityType: bodyMassType,
                                            quantitySamplePredicate: nil,
                                            options: [.mostRecent],
                                            anchorDate: anchorDate,
                                            intervalComponents: interval)
    query.initialResultsHandler = { _, results, error in
        guard let results = results else {
            print("ERROR")
            return
        }

        results.enumerateStatistics(from: startDate, to: now) { statistics, _ in
            // hier wieder .mostRecent!
            if let sum = statistics.mostRecentQuantity() {
                let bodyMassValue = sum.doubleValue(for: HKUnit.gramUnit(with: .kilo)).roundToDecimal(2)
                completion(bodyMassValue, statistics.startDate)
                return
            } 
        }
    }
    healthStore.execute(query)
}

Это загружает данные за последние n дней и возвращает bodyMass, а также дату

...