HealthKit: Asking For Identifying Information

I’m writing a small series on HealthKit as we’re approaching the New Year and the release of the WATCH, especially the Sports edition. For understanding HealthKit units, take a look at my first post: HealthKit: Let’s Talk About Units. In this post, I’m going to talk about getting your user’s personal data.

HKHealthStore

The HKHealthStore class provides an interface for accessing and storing the user’s health data. Since this is what you’re using to read and write from the HealthKit database, it’s best to just create this once. I like to wrap by healthStore constant in a singleton, which I use to interface with HealthKit.

let healthStore: HKHealthStore? = {
    if HKHealthStore.isHealthDataAvailable() {
        return HKHealthStore()
    } else {
        return nil
    }
}()

Note that the HealthStore is not available on all devices, so make sure to do an HKHealthStore.isHealthDataAvailable() check when instantiating your healthStore constant.

HKCharacteristicType

There are three pieces of personal information you can ask from the user:

  • Date of Birth
  • Biological Sex
  • Blood Type

Each of these are a special HKCharacteristicType. In other words, these are your user’s characteristics that do not change.

let dateOfBirthCharacteristic = HKCharacteristicType.characteristicTypeForIdentifier(
HKCharacteristicTypeIdentifierDateOfBirth)

let biologicalSexCharacteristic = HKCharacteristicType.characteristicTypeForIdentifier(
HKCharacteristicTypeIdentifierBiologicalSex)

let bloodTypeCharacteristic = HKCharacteristicType.characteristicTypeForIdentifier(
HKCharacteristicTypeIdentifierBloodType)

Asking For Permission

Remember, HealthKit contains very sensitive user information, so in order to get this information, the user has to give permission. Here is how you request the user’s permission:

let healthStore: HKHealthStore? = {
    if HKHealthStore.isHealthDataAvailable() {
        return HKHealthStore()
    } else {
        return nil
    }
}()

let dateOfBirthCharacteristic = HKCharacteristicType.characteristicTypeForIdentifier(
HKCharacteristicTypeIdentifierDateOfBirth)

let biologicalSexCharacteristic = HKCharacteristicType.characteristicTypeForIdentifier(
HKCharacteristicTypeIdentifierBiologicalSex)

let bloodTypeCharacteristic = HKCharacteristicType.characteristicTypeForIdentifier(
HKCharacteristicTypeIdentifierBloodType)

let dataTypesToRead = NSSet(objects:
            dateOfBirthCharacteristic,
            biologicalSexCharacteristic,
            bloodTypeCharacteristic)

healthStore?.requestAuthorizationToShareTypes(nil,
readTypes: dataTypesToRead,
completion: { (success, error) -> Void in
            if success {
                println("success")
            } else {
                println(error.description)
            }
        })

Requesting authorization will pop up this permission screen to the user:

HealthKit Permissions

Note that we can only request READ permission for characteristics. This is because it doesn’t make sense for multiple apps to re-write user’s data of birth for example. If the user wants to add their date of birth, they can only do so in the official Apple’s Health App! This is what happens when you try to request authorization for write this data:

HealthKit Authorization Denied

Querying for User Characteristics

Once you have the permission from the user to get their characteristic data, it’s very easy to query for their date of birth, biological sex, and blood type:

Date of Birth

Querying for date of birth returns an NSDate:

     var dateOfBirth: String? {
        if let dateOfBirth = healthStore?.dateOfBirthWithError(nil) {
            return dateFormatter.stringFromDate(dateOfBirth)
        }
        return nil
    }
    
    let dateFormatter: NSDateFormatter = {
        let formatter = NSDateFormatter()
        formatter.dateStyle = .ShortStyle
        return formatter
    }()

Biological Sex

Querying for biological sex returns an HKBiologicalSexObject, which includes a biologicalSex enum:

var biologicalSex: String? {
    if let biologicalSex = healthStore?.biologicalSexWithError(nil) {
        switch biologicalSex.biologicalSex {
        case .Female:
            return "Female"
        case .Male:
            return "Male"
        case .NotSet:
            return nil
        }
    }
    
    return nil
}

Blood Type

Querying for blood type returns an HKBloodTypeObject, which includes a bloodType enum:

var bloodType: String? {
    if let bloodType = healthStore?.bloodTypeWithError(nil) {
            
        switch bloodType.bloodType {
        case .APositive:
            return "A+"
        case .ANegative:
            return "A-"
        case .BPositive:
            return "B+"
        case .BNegative:
            return "B-"
        case .ABPositive:
            return "AB+"
        case .ABNegative:
            return "AB-"
        case .OPositive:
            return "O+"
        case .ONegative:
            return "O-"
        case .NotSet:
            return nil
        }
    }
    return nil
}

Note that I chose to make all of these objects computed properties. That is because the user can change permissions for any characteristic an any time! The data may or may not be there.

You can get the full code for retrieving user data on Github here. Make sure to read the README to get the project set up correctly!

Enjoy the article? Join over 14,500+ Swift developers and enthusiasts who get my weekly updates.