5

I am writing a simple app to monitor the heart rate (HKQuantityTypeIdentifierHeartRate) from HealthKit whenever a new health rate value is written to HealthKit.

As seen at WWDC2015 (session 203) I am using a HKAnchoredObjectQuery which should work for adding and deleting objects. Whenever I start the app I am calling the HKQuery for the newest objects and executingQuery which works fine!!! But I am getting no new samples even if the samples are there, but if I bring the app to the background and again to the foreground I am getting all the new heart rates. IS IT A BUG? Or what shall I do to monitor the heart rate without bringing the app to the back- and foreground?

Here is the code I am using (everything is stored in the AppDelegate), I am calling [self requestAccessDataTypes]; from didFinishLaunchingWithOptions:

[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;
}
4

2 回答 2

1

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

要获取 iOS 上的最新数据,不创建 WatchOS 应用程序是不可能的。使用 WatchOS 应用程序,您可以使用锻炼会话手表连接将心率数据发送到 iOS 应用程序每次发生变化时。

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

于 2015-12-02T11:02:09.777 回答
1

您错过了观察 HealthKit 变化的关键部分。它被称为HKObserverQuery

文档

观察者查询在后台队列上设置了一个长时间运行的任务。此任务监视 HealthKit 存储,并在匹配数据保存到存储或从存储中删除时提醒您。观察者查询让您的应用程序响应其他应用程序和设备所做的更改。

回顾

您必须启用后台交付才能收到有关更新的通知HKAnchoredObjectQueryHKObserverQuery然后,您可以在发生这种情况时执行您的查询。

注意 1:HKObserverQuery的更新处理程序不会给您任何 Apple Health 数据样本。您仍然必须HKAnchoredObjectQuery使用适当的锚来执行您的操作以获取样本。

注意 2:您必须在HKObserverQuery每次应用启动时进行设置。

有关更多信息,请在此处查看我的答案。

于 2016-02-05T06:30:12.960 回答