Apple HealthKit read Dietary Fibre using swift 5 - ios

I am trying to read the nutrition details from Health Kit, but getting empty array and error when I query the HealthKit.
func getNutritionDetails() {
let predicate = HKQuery.predicateForSamples(withStart: Date(), end: Date().addingTimeInterval(-1.0 * 60.0 * 60.0 * 24.0), options: .strictStartDate)
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: true)
let query = HKSampleQuery.init(
sampleType: HKQuantityType.quantityType(forIdentifier: .dietaryFiber)!,
predicate: predicate,
limit: 0,
sortDescriptors: [sortDescriptor]) { (query, samples, error) in
DispatchQueue.main.async {
print(samples, error)
}
}
self.healthStore.execute(query)
}
It prints Optional([]) nil
Also, what if I want to read the nutritions in one single query to HealthKit?

Related

Why does this always return 0? [duplicate]

This question already has answers here:
Returning data from async call in Swift function
(13 answers)
Closed 6 months ago.
I am trying to read the latest heart rate using HealthKit. My script is working fine, however when I try to return an integer value from my function it always returns 0 (the default value of latestHeartRateBPM), even though it is being mutated.
func getLatestHeartRate() -> Int {
var latestHeartRateBPM = 0
guard let sampleType = HKObjectType.quantityType(forIdentifier: .heartRate) else {
return 0
}
let startDate = Calendar.current.date(byAdding: .month, value: -1, to: Date())
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictEndDate)
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
let query = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: [sortDescriptor]) { (sample, result, error) in
guard error == nil else {
return
}
let data = result![0] as!HKQuantitySample
let unit = HKUnit(from: "count/s")
let latestHeartRateBPS = data.quantity.doubleValue(for: unit)
latestHeartRateBPM = Int(ceil(latestHeartRateBPS * 60))
}
healthStore?.execute(query)
return latestHeartRateBPM
}
As let query = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: [sortDescriptor]) { (sample, result, error) in is an asynchronous part , you need a completion
func getLatestHeartRate(completion:#escaping((Int?) -> ())) {
guard let sampleType = HKObjectType.quantityType(forIdentifier: .heartRate) else {
completion(nil)
}
let startDate = Calendar.current.date(byAdding: .month, value: -1, to: Date())
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictEndDate)
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
let query = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: [sortDescriptor]) { (sample, result, error) in
guard error == nil else {
completion(nil)
return
}
let data = result![0] as!HKQuantitySample
let unit = HKUnit(from: "count/s")
let latestHeartRateBPS = data.quantity.doubleValue(for: unit)
let latestHeartRateBPM = Int(ceil(latestHeartRateBPS * 60))
completion(latestHeartRateBPM)
}
healthStore?.execute(query)
}
Usage
getLatestHeartRate() { res in
print(res)
}

Apple healthKit REM, Deep, Light sleep analysis

I am working on an IOS sleep application where i need to do sleep analysis. I am using Healthkit for sleep data from where i can successfully fetch sleep analysis data using below code :
func retrieveSleepAnalysis(from startDate: Date?, to endDate: Date? , completion: #escaping ([HKCategorySample], Error?) -> Void) {
guard let sleepType = HKObjectType.categoryType(forIdentifier: .sleepAnalysis) else { return}
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: 10000, sortDescriptors: [sortDescriptor]) { (query, result, error) in
if error != nil {
completion([], error)
return
}
if let result = result {
let samples = result.compactMap({ $0 as? HKCategorySample})
completion(samples, nil)
}
}
// finally, we execute our query
HKHealthStore().execute(query)
}
I am not able to find any healthKit code for Sleep REM cycles , Deep sleep , light sleep etc. Is it even possible to get this data from healthKit ? if Yes , How to do it? , if not with healthKit, How to do it in IOS Applications ?
You may find what you're looking for in this year's WWDC talk on "What's New In HealthKit"
Here's how you can declare a predicate for all samples:
// Predicate for all asleep samples (unspecified, core, deep, REM)
let allAsleepPredicate = HKCategoryValueSleepAnalysis.predicateForSamples(equalTo: .allAsleepValues)
And here's how you might use it to fetch all samples in a range:
let healthStore = HKHealthStore()
let sleepType = HKCategoryType(.sleepAnalysis)
let dateRangePredicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictStartDate)
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [dateRangePredicate, allAsleepPredicate])
let query = HKSampleQuery(sampleType: sleepType, predicate: predicate) { (query, result, error) in
// handle results
}
Hope that helps

HKSampleQuery returns no results even when there are

I'm trying to get all heart rate samples from the past month, and extract the times and values from them.
So far, I've got the following method:
func getThisMonthsHeartRates() {
print("func called")
let heartRateUnit:HKUnit = HKUnit(from: "count/min")
let heartRateType:HKQuantityType = HKQuantityType.quantityType(forIdentifier: .heartRate)!
//predicate
let startDate = Date()
let endDate = Date() - 1.month
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: [])
//descriptor
let sortDescriptors = [
NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
]
let heartRateQuery = HKSampleQuery(sampleType: heartRateType,
predicate: predicate,
limit: Int(HKObjectQueryNoLimit),
sortDescriptors: sortDescriptors)
{ (query:HKSampleQuery, results:[HKSample]?, error:Error?) -> Void in
guard error == nil else { print("error"); return }
print("results")
print(results!)
for result in results! {
guard let currData:HKQuantitySample = result as? HKQuantitySample else { return }
print("Heart Rate: \(currData.quantity.doubleValue(for: heartRateUnit))")
print("quantityType: \(currData.quantityType)")
print("Start Date: \(currData.startDate)")
print("End Date: \(currData.endDate)")
print("Metadata: \(String(describing: currData.metadata))")
print("UUID: \(currData.uuid)")
print("Source: \(currData.sourceRevision)")
print("Device: \(String(describing: currData.device))")
print("---------------------------------\n")
}
} //eo-query
healthStore.execute(heartRateQuery)
}//eom
However, the results will always return an empty array, even though I've got samples on my device! Really curious as to how this can be and how to fix it. I'm at a total loss.
Thanks
Update
After logging the query before it gets executed and while it's being executed, this is what the console says:
<HKSampleQuery:0x1c4117610 inactive>
And
<HKSampleQuery:0x1c4117610 deactivated>
I have no idea what this means nor can I find anything online about it.
The problem might be that you have requested authorization to write .heartRate sample types, but not to read them as well. In this case you don't receive an error when executing the query, however the samples array will be empty.
I had the same problem because I was requesting authorization this way:
healthStore.requestAuthorization(toShare: types, read: nil) {}
Instead, you need to specify the types that you want to read even though they are already in the types set.

How can I fetch the most recent weight entry from HealthKit data for each Day in a defined time interval

Hello I want to grab the latest datapoint for body mass of each day in a defined time interval
(in my case I need it for an interval of one week but only the last entry for each day.)
Actually, Using this code I can get all the entries from start X date to the end X date
let query = HKSampleQuery(sampleType: type!, predicate: predicate,
limit: 0, sortDescriptors: nil, resultsHandler: { (query, results, error) in
if let myResults = results {
for result in myResults {
let bodymass = result as! HKQuantitySample
let weight = bodymass.quantity.doubleValue(for: unit)
Print ("this is my weight value",weight )
}
}
else {
print("There was an error running the query: \(String(describing: error))")
}
This query returns any samples measuring weight consumed that fall within the time frame.
I just want to return the last entry recorded is there any way to do it with heath-kit query?
I've tried to define sort descriptor but I don’t find a way to make it work with defined time interval.
Thanks
I read this and this one
As you said you want to use a sort descriptor, just use Date.distantPast and Date() as your range, then just grab the first:
func getUserBodyMass(completion: #escaping (HKQuantitySample) -> Void) {
guard let weightSampleType = HKSampleType.quantityType(forIdentifier: .bodyMass) else {
print("Body Mass Sample Type is no longer available in HealthKit")
return
}
//1. Use HKQuery to load the most recent samples.
let mostRecentPredicate = HKQuery.predicateForSamples(withStart: Date.distantPast,
end: Date(),
options: [])
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate,
ascending: false)
let limit = 1
let sampleQuery = HKSampleQuery(sampleType: weightSampleType,
predicate: mostRecentPredicate,
limit: limit,
sortDescriptors: [sortDescriptor]) { (query, samples, error) in
//2. Always dispatch to the main thread when complete.
DispatchQueue.main.async {
guard let samples = samples,
let mostRecentSample = samples.first as? HKQuantitySample else {
print("getUserBodyMass sample is missing")
return
}
completion(mostRecentSample)
}
}
healthStore.execute(sampleQuery)
}

Cannot find an initializer for type

let endDate = NSDate()
let startDate = NSDate()
let v : Float?
let stepsCount:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)!
let predicate:NSPredicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: .None)
let query = HKQuantitySample(sampleType: stepsCount, predicate: predicate, limit: 1, sortDescriptors: nil, resultsHandler: {
(query, results, error) in
if results == nil {
print(error)
}
v = result.first.Quantity
})
healthStore.executeQuery(query)
Cannot find an initializer for type 'HKQuantitySample' that accepts
an argument list of type '(sampleType: HKQuantityType, predicate:
NSPredicate, limit: Int, sortDescriptors: nil, resultsHandler: (_, _,
_) -> _)'
Just replace HKQuantitySample with HKSampleQuery and it will work fine.
For more Info refer THIS tutorial.
Where you can find sample code like:
func readMostRecentSample(sampleType:HKSampleType , completion: ((HKSample!, NSError!) -> Void)!)
{
// 1. Build the Predicate
let past = NSDate.distantPast() as! NSDate
let now = NSDate()
let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(past, endDate:now, options: .None)
// 2. Build the sort descriptor to return the samples in descending order
let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)
// 3. we want to limit the number of samples returned by the query to just 1 (the most recent)
let limit = 1
// 4. Build samples query
let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: mostRecentPredicate, limit: limit, sortDescriptors: [sortDescriptor])
{ (sampleQuery, results, error ) -> Void in
if let queryError = error {
completion(nil,error)
return;
}
// Get the first sample
let mostRecentSample = results.first as? HKQuantitySample
// Execute the completion closure
if completion != nil {
completion(mostRecentSample,nil)
}
}
// 5. Execute the Query
self.healthKitStore.executeQuery(sampleQuery)
}
Documentation doesn't talk about any initializer like the one you are providing… Even looked in the Beta docs and didn't found anything about the one you are trying to call.
Please look here for existing HKQuantitySample initializers available :
https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HKQuantitySample_Class/
See Dharmesh Kheni's answer for the correct way to create a query :).

Resources