Error Code #3, or ‘The Adventure of Deleting a HealthKit Object’

“An invalid argument was provided to the HealthKit API.”

This dreaded error has a code of #3. It signifies my lack of knowledge about how HealthKit works, as well as how it should work.

Unfortunately, duplicate samples can be added to Health. If the framework relied on indexOf to delete an object with matching properties, only the first occurrence would be deleted. Therefore, Apple doesn’t want to prescribe a deletion method, relying instead on shared identifiers between the exact same instances.

Because of this, instantiating a new HKObject (HKCategorySample in my case) with any properties and passing it to the delete method will throw an error like the one above.

While I was debugging this issue, I thought it was ridiculous that an error message blaming the source code would be used to communicate that a HealthKit object couldn’t be found (“Failed to find some objects for deletion”). However, it turns out that the code looked fine on the surface, while actually assuming the existence of a flaw in HealthKit’s design, by expecting it to figure out which exact object to delete.

My (now obvious) solution was to iterate over the results of an HKSampleQuery and delete the first object that shares properties with the custom object set for deletion by the user. If you just can’t ignore duplicates at runtime and want to avoid unexpected behavior (which, of course, was the whole point of HealthKit not using indexOf), you can keep track of which Nth occurrence to delete with a similar loop.

Sourced from Allan’s Stack Overflow post.