Swift 2.0:读取 HealthKit 心率数据 - 在展开 Optional 时意外发现 nil

Posted

技术标签:

【中文标题】Swift 2.0:读取 HealthKit 心率数据 - 在展开 Optional 时意外发现 nil【英文标题】:Swift 2.0: Reading HealthKit HeartRate Data - unexpectedly found nil while unwrapping an Optional 【发布时间】:2015-09-20 21:09:25 【问题描述】:

我正在尝试对 HealthKit 中的心率数据进行统计查询。

以下代码编译成功,但在函数调用时出现以下错误:

致命错误:在展开可选值时意外发现 nil

错误发生在这一行:

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

为什么结果返回 nil?我已验证 HealthKit 中提供了心率数据,所以我不认为这是因为查询中的数据不存在。

有什么想法吗?有一个更好的方法吗?

代码如下:

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)

【问题讨论】:

你看error了吗? 发生错误,因为 'result' 为 nil。我的问题是为什么应该有数据时查询返回 nil? 对,但是有一个 error 参数应该告诉你发生了什么。 【参考方案1】:

result 参数不保证为非零。如果结果不是 nil,您应该只打开并使用它,否则检查 error 以查看问题所在。有许多您可能无法控制的错误可能会发生(例如,在处理您的查询时设备可能会被锁定,或者执行查询的系统守护程序可能会崩溃)。

【讨论】:

好点。我会尝试添加一个完成处理程序,看看我是否能捕捉到正在发生的事情。【参考方案2】:

我最终在这里采用了不同的方法,并能够通过手动查询一组心率数据并取平均值来解决问题。

注意:getDayofWeek 函数只接受 NSDate 并返回星期几的字符串。

    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)

【讨论】:

以上是关于Swift 2.0:读取 HealthKit 心率数据 - 在展开 Optional 时意外发现 nil的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Swift 从 iOS HealthKit 应用程序读取心率?

如何使用 Swift 从 iOS HealthKit 应用程序读取心率?

Swift HealthKit 触发心率样本

如何使用 Swift 查询 Healthkit 的平均心率

如何使用 Swift 查询 Healthkit 的平均心率

iOS HealthKit 如何保存心率(bpm)值?迅速