0000101010
0000101010

Reputation: 705

Swift 2.0: Reading HealthKit HeartRate Data - unexpectedly found nil while unwrapping an Optional

I am trying a statistical query for Heart Rate data in HealthKit.

The below code compiles but results in the following error upon function call:

fatal error: unexpectedly found nil while unwrapping an Optional value

The error occurs on this line:

let quantity : HKQuantity = result!.averageQuantity()!;

Why is result returning nil? I have verified that Heart Rate data is available in HealthKit so I don't believe it's because the data in the query does not exist.

Any Ideas? Is there a better way to do this?

Code below:

func readHeartRate() {
    let sampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)!
    let nowDate = NSDate()
    let calendar = NSCalendar.autoupdatingCurrentCalendar()

    let yearMonthDay: NSCalendarUnit = [NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.Day]

    let components: NSDateComponents = calendar.components(yearMonthDay , fromDate: nowDate)
    let beginOfDay : NSDate = calendar.dateFromComponents(components)!
    let predicate : NSPredicate = HKQuery.predicateForSamplesWithStartDate(beginOfDay, endDate: nowDate, options: HKQueryOptions.StrictStartDate)

    let squery = HKStatisticsQuery(quantityType: sampleType, quantitySamplePredicate: predicate, options: HKStatisticsOptions.None, completionHandler: { (squery, result, error) -> Void in

        dispatch_async( dispatch_get_main_queue(), { () -> Void in

            let quantity : HKQuantity = result!.averageQuantity()!;
            let beats : Double = quantity.doubleValueForUnit(self.heartRateUnit)
            print(beats)
        })
    })

    healthKitStore.executeQuery(squery)
}

Upvotes: 3

Views: 596

Answers (2)

0000101010
0000101010

Reputation: 705

I ended up taking a different approach here and was able to solve the problem by manually by querying for a set of Heart Rate data and taking the average.

Note: getDayofWeek function just takes an NSDate and returns a string for the day of week.

    func readHRbyDate(latestXSamples: Int, startDate: NSDate, endDate: NSDate, completion: (((String, CGFloat), NSError!) -> Void)!)
{
    let sampleType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)
    let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: HKQueryOptions.None)
    let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)

    var HRdata:(String,CGFloat) = ("N/A",0)
    var bpm: Int = 0

    var totalBPMforDay = [Int]()
    var BPMCount: Int = 0

    var sumBPM: Int = 0

    let query = HKSampleQuery(sampleType: sampleType!, predicate: predicate, limit: latestXSamples, sortDescriptors: [sortDescriptor])
        { (query, results, error) in
            if let queryError = error {
                print("Problem fetching HR data")
                completion(("nil",0.0),queryError)
                return
            }else{
                for result in results! {
                    bpm = Int(((result.valueForKeyPath("_quantity._value"))?.floatValue)! * 60.0)
                    totalBPMforDay += [Int(((result.valueForKeyPath("_quantity._value"))?.floatValue)! * 60.0)]
                    BPMCount = Int(totalBPMforDay.count)
                    sumBPM += Int(((result.valueForKeyPath("_quantity._value"))?.floatValue)! * 60.0)

                    let HRAvg = sumBPM / BPMCount

                    HRdata = (self.getDayOfWeek(result.startDate),CGFloat(HRAvg))
                }
                if completion != nil {
                    completion(HRdata,nil)
                }
            }
    }

    healthKitStore.executeQuery(query)
}

Upvotes: 0

Allan
Allan

Reputation: 7353

The result parameter is not guaranteed to be non-nil. You should only unwrap and use result if it is not nil, and otherwise examine error to see what went wrong. There are a number of errors that you could expect to occur that are outside of your control (for instance the device could become locked while processing your query or the system daemon performing the query could crash).

Upvotes: 1

Related Questions