Deleting a Water Sample from HealthKit
Asked Answered
N

2

1

My application currently lets users save WaterIntakeRecords and they are then persisted with Core Data. I am able to write to HealthKit, saving a water intake record as a HKQuantitySample.

I add a WaterIntakeRecord into my application with an amount of 12.9 fluid ounces. Since in Health, I have milliliters as my preferred unit of measurement, it shows in milliliters:

enter image description here

Where I am struggling is when trying to delete a sample.

When the user saves a WaterIntakeRecord, they can choose the unit of measurement that they want to save the sample in, and then it converts that measurement to US ounces, which is a property of WaterIntakeRecord. This way, every WaterIntakeRecord has a consistent unit of measurement that can be converted into other units of measurement (all the ones found in Health) for display.

When trying to delete a saved sample, I try this:

static func deleteWaterIntakeSampleWithAmount(amount: Double, date: NSDate) {

    guard let type = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDietaryWater) else {
        print("———> Could not retrieve quantity type for identifier")
        return
    }

    let quantity = HKQuantity(unit: HKUnit.fluidOunceUSUnit(), doubleValue: amount)

    let sample = HKQuantitySample(type: type, quantity: quantity, startDate: date, endDate: date)

    HealthKitStore.deleteObject(sample) { (success, error) -> Void in
        if let err = error {
            print("———> Could not delete water intake sample from HealthKit: \(err)")
        } else {
            print("———> Deleted water intake sample from HealthKit")
        }
    }
}

When the user deletes a record in my application, it should delete the corresponding sample in HealthKit. The record is successfully deleted from my application, however, I keep getting an error when attempting to delete the sample from HealthKit, using the method above:

Error Domain=com.apple.healthkit Code=100 "Transaction failure." UserInfo {NSLocalizedDescription=Transaction failure.}

I'm not sure what I am doing incorrectly to keep getting this error.

The amount parameter is the WaterIntakeRecord's ouncesUS value, and the date parameter is the WaterIntakeRecords date property which is the creation date of the record:

Any ideas on where I am causing the deletion to fail?

Nonesuch answered 10/3, 2016 at 17:1 Comment(0)
N
2

Each sample in HealthKit is unique. When deleting a sample, you must first query for the sample that your app saved originally and then use it in your call to HealthKitStore.deleteObject(). In your code snippet above, you are creating a new, unsaved sample then attempting to delete it.

Nakasuji answered 11/3, 2016 at 7:46 Comment(1)
Thanks, Allan! I was able to rectify my situation by doing just what you suggested. I queried the HealthKit store and found the intended record to delete.Nonesuch
S
3

Indeed, a sample has to be queried and retrieved from health store before deletion. Below is the code i used in obj-c as a jump start for anyone new with this stuff:

// get an instance of the health store
self.healthStore = [[HKHealthStore alloc] init];

// the interval of the samples to delete (i observed that for a specific value if start and end date are equal the query doesn't return any objects)
NSDate *startDate = [dateOfSampleToDelete dateByAddingTimeInterval:0];
NSDate *endDate = [dateOfSampleToDelete dateByAddingTimeInterval:1];

// the type you're trying to delete (this could be heart-beats/steps/water/calories/etc..)
HKQuantityType *waterType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierDietaryWater];

// the predicate used to execute the query
NSPredicate *queryPredicate = [HKSampleQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];

// prepare the query
HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:waterType predicate:queryPredicate limit:100 sortDescriptors:nil resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {

    if (error) {

        NSLog(@"Error: %@", error.description);

    } else {

        NSLog(@"Successfully retreived samples");

        // now that we retrieved the samples, we can delete it/them
        [self.healthStore deleteObject:[results firstObject] withCompletion:^(BOOL success, NSError * _Nullable error) {

            if (success) {

                NSLog(@"Successfully deleted entry from health kit");

            } else {

                NSLog(@"Error: %@", error.description);

            }
        }];

    }
}];

// last but not least, execute the query
[self.healthStore executeQuery:query];

A better practice would be to check we indeed have an object to delete before executing the [results firstObject] part of the above solution

Shoebill answered 8/7, 2016 at 9:23 Comment(0)
N
2

Each sample in HealthKit is unique. When deleting a sample, you must first query for the sample that your app saved originally and then use it in your call to HealthKitStore.deleteObject(). In your code snippet above, you are creating a new, unsaved sample then attempting to delete it.

Nakasuji answered 11/3, 2016 at 7:46 Comment(1)
Thanks, Allan! I was able to rectify my situation by doing just what you suggested. I queried the HealthKit store and found the intended record to delete.Nonesuch

© 2022 - 2024 — McMap. All rights reserved.