Получить самую последнюю точку данных из HKSampleQuery

У меня возникли проблемы с получением последней точки данных для веса с помощью HKSampleQuery. У меня правильно установлены разрешения для приложения, но HKQuantityTypeIdentifier.bodyMass не возвращает самые последние данные из приложения Health.

Как мне получить последние данные по массе тела с помощью HKSampleQuery?

Причина, по которой я так думаю, заключается в том, что значение 0.0, которое я установил для Weight, — это то, что возвращается, и я не получаю вывод консоли на readWeight.


Изменить 1

Мой код, включая процесс отладки, выглядит следующим образом.

public func readWeight(result: @escaping (Double) -> Void) {
    if (debug){print("Weight")}
    let quantityType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)

    let weightQuery = HKSampleQuery(sampleType: quantityType!, predicate: nil, limit: 1, sortDescriptors: nil) {

        query, results, error in

        if (error != nil) {
            if (self.debug){print(error!)}
            result(166.2) //Set as average weight for American
            return
        }

        guard let results = results else {
            if (self.debug){print("No results of query")}
            result(166.2)
            return
        }

        if (results.count == 0) {
            if (self.debug){print("Zero samples")}
            result(166.2)
            return
        }

        guard let bodymass = results.first as? HKQuantitySample else {
            if (self.debug){print("Type problem with weight")}
            result(166.2)
            return
        }

        if (self.debug){print("Weight" + String(bodymass.quantity.doubleValue(for: HKUnit.pound())))}

        if (bodymass.quantity.doubleValue(for: HKUnit.pound()) != 0.0) {
            result(bodymass.quantity.doubleValue(for: HKUnit.pound()))
        } else {
            result(166.2)
        }
    }

    healthKitStore.execute(weightQuery)
}

Функция используется следующим образом:

var Weight = 0.0 //The probable reason that it returns 0.0
readWeight() { weight in
    Weight = weight
}

Редактировать 2

Код разрешения:

    let healthKitTypesToRead : Set<HKQuantityType> = [
        HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryWater)!,
        HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!,
        HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.appleExerciseTime)!
    ]

    let healthKitTypesToWrite: Set<HKQuantityType> = [
        HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.dietaryWater)!
    ]

    if (!HKHealthStore.isHealthDataAvailable()) {
        if (self.debug){print("Error: HealthKit is not available in this Device")}
        return
    }

    healthKitStore.requestAuthorization(toShare: healthKitTypesToWrite, read: healthKitTypesToRead) { (success, error) -> Void in
        if (success) {
            DispatchQueue.main.async() {
                self.pointView.text = String(self.currentPoints())
            }
        }

        if ((error) != nil) {
            if (self.debug){print(error!)}
            return
        }

person arodebaugh    schedule 30.06.2017    source источник
comment
Пожалуйста, включите свой код и описание отладки, которую вы уже сделали.   -  person Allan    schedule 02.07.2017
comment
Попался @Allan, позвольте мне отредактировать мой вопрос   -  person arodebaugh    schedule 03.07.2017
comment
@Allan сделал, кстати, я также использовал точки останова, чтобы попытаться отладить его.   -  person arodebaugh    schedule 03.07.2017
comment
@arodebaugh Для дальнейшего использования, пожалуйста, не используйте тег swift3 (или любой другой тег языка и версии), если ваш вопрос не конкретно об изменениях, внесенных в сам язык между версиями. Вместо этого вы можете указать язык, который вы используете, в теле вопроса.   -  person Sam Spencer    schedule 07.07.2017


Ответы (1)


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

В вашем случае возврат самой последней точки данных может быть выполнен несколькими способами. Взгляните на HKSampleQuery и следующий метод:

init(sampleType:predicate:limit:sortDescriptors:resultsHandler:)

Вы можете указать порядок сортировки возвращаемых образцов или ограничить количество возвращаемых образцов.

-- Документация по HKSampleQuery

В своем коде вы соответствующим образом ограничили запрос, чтобы он возвращал только один образец. Это правильно и позволяет избежать ненужных накладных расходов в вашем случае использования. Однако ваш код указывает nil для параметра sortDescriptors. Это означает, что запрос может возвращать образцы в любом порядке (таким образом, возвращаемый вам один образец обычно не является тем, что вы ищете).

Массив дескрипторов сортировки, определяющих порядок результатов, возвращаемых этим запросом. Передайте nil, если вам не нужны результаты в определенном порядке.

Примечание
HealthKit определяет ряд идентификаторов сортировки (например, HKSampleSortIdentifierStartDateи HKWorkoutSortIdentifierDuration). Используйте дескрипторы сортировки, которые вы создаете с этими идентификаторами, только в запросах. Вы не можете использовать их для выполнения сортировки массива образцов в памяти.

-- Документация по HKSampleQuery.init(...)< /а>

Таким образом, решение состоит в том, чтобы просто предоставить дескриптор сортировки, который просит HKSampleQuery упорядочить образцы по дате в порядке убывания (это означает, что самые последние будут первыми в списке).


Я надеюсь, что приведенный выше ответ будет более полезным, чем простое копирование/вставка кода, необходимого для решения проблемы. Тем не менее код, обеспечивающий правильный пример для этого конкретного варианта использования, приведен ниже:

// Create an NSSortDescriptor
let sort = [
    // We want descending order to get the most recent date FIRST
     NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
]

let weightQuery = HKSampleQuery(sampleType: quantityType!, predicate: nil, limit: 1, sortDescriptors: sort) {
    // Handle errors and returned samples...
}
person Sam Spencer    schedule 07.07.2017