问题
My application currently lets users save WaterIntakeRecord
s 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:
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 WaterIntakeRecord
s date
property which is the creation date of the record:
Any ideas on where I am causing the deletion to fail?
回答1:
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.
回答2:
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
来源:https://stackoverflow.com/questions/35922734/deleting-a-water-sample-from-healthkit