I'm following some tutorials on HealthKit using swift, one of the tutorials I'm following is how to retrieve some data from the HealthKit such as weight, height age. The tutorial shows how to retrieve the most recent record for each them, the following codes shows that:
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)
}
Then in other class the developer passes the parameters to get the required most recent record, the following code shows the method that retrieves the height record:
func updateHeight()
{
// 1. Construct an HKSampleType for Height
let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight)
// 2. Call the method to read the most recent Height sample
self.healthManager?.readMostRecentSample(sampleType, completion: { (mostRecentHeight, error) -> Void in
if( error != nil )
{
println("Error reading height from HealthKit Store: \(error.localizedDescription)")
return;
}
var heightLocalizedString = self.kUnknownString;
self.height = mostRecentHeight as? HKQuantitySample;
// 3. Format the height to display it on the screen
if let meters = self.height?.quantity.doubleValueForUnit(HKUnit.meterUnit()) {
let heightFormatter = NSLengthFormatter()
heightFormatter.forPersonHeightUse = true;
heightLocalizedString = heightFormatter.stringFromMeters(meters);
}
// 4. Update UI. HealthKit use an internal queue. We make sure that we interact with the UI in the main thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.heightLabel.text = heightLocalizedString
self.updateBMI()
});
})
}
I created a similar method to the first one, but with few changes so I can get an array of 10 glucose records:
func readAllGlucose(sampleType:HKSampleType , completion: (([HKSample!], NSError!) -> Void)!)
{
let now = NSDate()
let df = NSDateFormatter()
df.dateFormat = "yyyy-MM-dd"
let pastt = df.dateFromString("2015-05-18")
//let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(past, endDate:now, options: .None)
let allreadings = HKQuery.predicateForSamplesWithStartDate(pastt, 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 = 10
// 4. Build samples query
let sampleQuery = HKSampleQuery(sampleType: sampleType, predicate: allreadings, limit: limit, sortDescriptors: [sortDescriptor])
{ (sampleQuery, results, error ) -> Void in
if let queryError = error {
completion([nil],error)
return;
}
// Get the first sample
let allSamples = results as? [HKQuantitySample]
// Execute the completion closure
if completion != nil {
completion(allSamples!,nil)
}
}
// 5. Execute the Query
self.healthKitStore.executeQuery(sampleQuery)
}
Then I created another method similar to updateHeight() method,but of course with doing the necessary changes:
func updateLastGlucoRecords()
{
// 1. Construct an HKSampleType for weight
let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBloodGlucose)
// 2. Call the method to read the most recent weight sample
self.healthManager?.readAllGlucose(sampleType, completion: {([allReadings], error) -> Void in
if (error != nil) {
println("Error reading glucose readings from HealthKit Store: \(error.localizedDescription)")
return;
}
var glucoseLocalizedString = self.kUnknownString;
self.glucose = allReadings as? [HKQuantitySample]
for reading in readings {
if let record = reading.quantity {
glucoseLocalizedString = record
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.glucoReadings.append("\(glucoseLocalizedString)")
})
}
})
self.healthManager?.readMostRecentSample(sampleType, completion: { (mostRecentWeight, error) -> Void in
if( error != nil )
{
println("Error reading weight from HealthKit Store: \(error.localizedDescription)")
return;
}
var weightLocalizedString = self.kUnknownString;
// 3. Format the weight to display it on the screen
self.weight = mostRecentWeight as? HKQuantitySample;
if let kilograms = self.weight?.quantity.doubleValueForUnit(HKUnit.gramUnitWithMetricPrefix(.Kilo)) {
let weightFormatter = NSMassFormatter()
weightFormatter.forPersonMassUse = true;
weightLocalizedString = weightFormatter.stringFromKilograms(kilograms)
}
// 4. Update UI in the main thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.weightLabel.text = weightLocalizedString
self.updateBMI()
});
});
}
But unfortunately I'm getting two errors at the line:
self.healthManager?.readAllGlucose(sampleType, completion: {([allReadings], error) -> Void in
first error:
[HKSample!]' is not a subtype of '<>
second error:
Use of undeclared type 'allReadings'
If someone have any idea that could solve this problem I will be thankful and grateful for that
thanks in advance