iosswiftswift2healthkithksamplequery

How to get cycling duration from HealthKit for ios app using Swift


I am creating an app where I am reading data from health-Kit. I am able to read number of steps, Running + Walking etc. now i am trying to read the date and duration of cycling. This is what I was using for Running + Walking

func readDistanceWalkingRunning(completion: (([AnyObject]!, NSError!) -> Void)!) {
    let runningWalking = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)
    let predicate = HKQuery.predicateForSamplesWithStartDate(NSDate().dateByAddingTimeInterval(-86400.0), endDate: NSDate(), options: HKQueryOptions.None)

    let stepsSampleQuery = HKSampleQuery(sampleType: runningWalking!,
                                         predicate: predicate,
                                         limit: 100,
                                         sortDescriptors: nil)
    { [weak self] (query, results, error) in

        if let results = results as? [HKQuantitySample] {

            for result in results {
                print(" Distance was " + " \(result.quantity.doubleValueForUnit(HKUnit.mileUnit())) ")
                print("Date was " + "\(result.startDate)")

            }
        }
    }

    // Don't forget to execute the Query!
    executeQuery(stepsSampleQuery)
}

And everything is fine, But when I try to read distance for cycling using the code below, I am getting nil result. Cycling data is showing in appleHealth app but Why am I getting result as nil ? Please help

    func readDistanceCycling(completion: (([AnyObject]!, NSError!) -> Void)!) {
    let distanceCycling = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceCycling)
    let predicate = HKQuery.predicateForSamplesWithStartDate(NSDate(), endDate: NSDate(), options: HKQueryOptions.None)

    let query = HKSampleQuery(sampleType: distanceCycling!, predicate: predicate, limit: 100, sortDescriptors: nil, resultsHandler: { query, result, error in


if result != nil
{
    print("We have some Data")
}
else
{
    print("Result is nil")
}

if let results = result as? [HKQuantitySample] {

    for result in results {
        print(" Quantity type " + " \(result.quantityType) ")
        print("Date was " + "\(result.startDate)")

    }
}
})

    executeQuery(query)
    }


    }

Solution

  • Use given below function. It give you leatest 7 record. According to your requirement you can also change it.

    func getHealthDataValue ( HealthQuantityType : HKQuantityType , strUnitType : String , GetBackFinalhealthData: ((( healthValues : [AnyObject] ) -> Void)!) )
    {          
        if let heartRateType = HKQuantityType.quantityTypeForIdentifier(HealthQuantityType.identifier)
        {
            if (HKHealthStore.isHealthDataAvailable()  ){
    
                let sortByTime = NSSortDescriptor(key:HKSampleSortIdentifierEndDate, ascending:false)
    
                //            let timeFormatter = NSDateFormatter()
                //            timeFormatter.dateFormat = "hh:mm:ss"
                //yyyy-MM-dd'T'HH:mm:ss.SSSZZZZ
    
                let dateFormatter = NSDateFormatter()
                dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
    
            let query = HKSampleQuery(sampleType:heartRateType, predicate:nil, limit:7, sortDescriptors:[sortByTime], resultsHandler:{(query, results, error) in
    
                guard let results = results else {
    
                    //include the healthkit error in log
                    if let errorDescription = error!.description as String?
                    {
    
                        GetBackFinalhealthData (healthValues: ["nodata"])
                    }
                    return
                }
    
                var arrHealthValues     = [AnyObject]()
    
                for quantitySample in results {
                    let quantity = (quantitySample as! HKQuantitySample).quantity
                    let healthDataUnit : HKUnit
                    if (strUnitType.length > 0 ){
                        healthDataUnit = HKUnit(fromString: strUnitType)
                    }else{
                        healthDataUnit = HKUnit.countUnit()
                    }
    
                    let tempActualhealthData = "\(quantity.doubleValueForUnit(healthDataUnit))"
                    let tempActualRecordedDate = "\(dateFormatter.stringFromDate(quantitySample.startDate))"
                    if  (tempActualhealthData.length > 0){
                        let dicHealth : [String:AnyObject] = [HealthValue.kIdentifierValue :tempActualhealthData , HealthValue.kRecordDate :tempActualRecordedDate , HealthValue.kIdentifierDisplayUnit : strUnitType ]
    
                        arrHealthValues.append(dicHealth)
                    }
                }
    
                if  (arrHealthValues.count > 0)
                {
                    GetBackFinalhealthData (healthValues: arrHealthValues)
                }
                else
                {
                    GetBackFinalhealthData (healthValues: [HealthValue.kNoData])
                }
            })
            (self.HealthStore as! HKHealthStore).executeQuery(query)
        }
    }
    

    }

    Use above function as follow. Here you need to pass a type and unit.

    self.getHealthDataValue(HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBloodPressureDiastolic), strUnitType: "mmHg"
                    ) { (arrHealth) -> Void in                  
                }