从 HealthKit 监测心率 --> HKAnchoredObjectQuery 仅在 applicationDidBecomeActive 之后调用(BUG 或 FEATURE?)

Monitor heart rate from HealthKit --> HKAnchoredObjectQuery only called after applicationDidBecomeActive (BUG or FEATURE?)

我正在编写一个简单的应用程序,以便在将新的健康率值写入 HealthKit 时从 HealthKit 监控心率 (HKQuantityTypeIdentifierHeartRate)。

正如在 WWDC2015(会话 203)中看到的那样,我正在使用 HKAnchoredObjectQuery,它应该可以用于添加和删除对象。每当我启动应用程序时,我都会为最新的对象调用 HKQuery,并且 executingQuery 工作正常!!!但是即使有样本,我也没有得到新的样本,但是如果我将应用程序带到后台,然后再转到前台,我就会得到所有新的心率。这是一个错误吗?或者不把app调到后台和前台怎么监测心率?

这是我正在使用的代码(所有内容都存储在 AppDelegate 中),我从 didFinishLaunchingWithOptions:

调用 [self requestAccessDataTypes];
[healthStore enableBackgroundDeliveryForType:sampleType frequency:HKUpdateFrequencyImmediate withCompletion:^(BOOL success, NSError *error) {}];

HKQuery *query = [self createHeartRateStreamingQuery:datum];
    if (query) {
        [healthStore executeQuery:query];
    }
    else
    {
        NSLog(@"workout can not start");
    }

-(HKQuery*)createHeartRateStreamingQuery:(NSDate*)workoutStartDate
{
    NSLog(@"%@ - createHeartRateStreamingQuery", [self class]);

    if ([HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]) {
        HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];

        HKAnchoredObjectQuery * heartRateQuery = [[HKAnchoredObjectQuery alloc] initWithType:quantityType predicate:nil anchor:anchor limit:HKObjectQueryNoLimit resultsHandler:^(HKAnchoredObjectQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable sampleObjects, NSArray<HKDeletedObject *> * _Nullable deletedObjects, HKQueryAnchor * _Nullable newAnchor, NSError * _Nullable error) {

            if (!error) {
                anchor = newAnchor;
                [self updateHeartRate:sampleObjects];

            }

        }];
        heartRateQuery.updateHandler = ^void(HKAnchoredObjectQuery *query, NSArray<__kindof HKSample *> * __nullable addedObjects, NSArray<HKDeletedObject *> * __nullable deletedObjects, HKQueryAnchor * __nullable newAnchor, NSError * __nullable error)
        {
            if (!error) {
                anchor = newAnchor;
                [self updateHeartRate:addedObjects];

            }

        };
        return heartRateQuery;
    }
    return nil;
}

目前(iOS 9.1,WatchOS 2.0.1),无法通过 iOS 应用程序从 HealthKit 获取最新数据。这在 WWDC 演示中是可能的,因为代码是 运行 在 WatchOS 应用程序的 ExtensionDelegate 而不是 iOS 应用程序上。有一份 rdar 错误报告已提交 here

要获取有关 iOS 的最新数据,不创建 WatchOS 应用程序是不可能的。使用 WatchOS 应用程序,您可以使用 Workout Session and Watch Connectivity 每次更改时将心率数据发送到 iOS 应用程序。

当然,如果您的心率数据不是来自 Apple Watch,这也无济于事。希望它会在即将发布的版本中得到修复。

您缺少观察 HealthKit 变化的关键部分。它被称为HKObserverQuery

Docs

Observer queries set up a long-running task on a background queue. This task watches the HealthKit store, and alerts you whenever matching data is saved to or removed from the store. Observer queries let your app respond to changes made by other apps and devices.

回顾:

您必须将 HKAnchoredObjectQuery 包装在 HKObserverQuery 中并启用后台传送才能收到有关更新的通知。然后,只要发生这种情况,您就可以执行查询。

注意 1:HKObserverQuery 的更新处理程序不会为您提供任何 Apple Health 数据样本。您仍然需要使用适当的锚点来执行您的 HKAnchoredObjectQuery 以获得样本。

注意 2:您必须在每次启动应用程序时设置 HKObserverQuery

更多信息,请查看我的回答here