Добавление сексуальной активности в Apple Health через HealthKit

Существует множество примеров того, как добавить пульс или количество шагов в Apple Health через HealthKit. Я создал приложение, позволяющее отслеживать вашу сексуальную активность. И теперь я хочу добавить поддержку HealthKit.

Предварительные условия

После создания приложения в Xcode добавьте возможность HealthKit и добавьте строку в Info.plist.

Для ясности и лучшей практики мы создадим класс, который будет обрабатывать подключение к HealthKit. Вы можете добавить это и в представление. Но это будет некрасиво.

Образец против объекта

Образец — это то, что записывается в HKHealthStore, а объект — это то, что считывается из HKHealthStore.

HealthConnector

Пользовательский класс HealthConnector облегчает взаимодействие с HKHealthStore. В настоящее время он имеет две три функции:

  • requestAuthorization
  • saveSample
  • deleteObject

Запрос авторизации

Перед любым взаимодействием с HKHealthStore мы должны запросить разрешение. Недостаточно спросить один раз. Пользователь может отозвать разрешение, когда мы не смотрим.

Вы должны специально запросить типы образцов, из которых вы хотите читать и в которые хотите писать. Поскольку мое приложение только записывает образцы, но ничего не получает, requestAuthorization в read-параметре nil.

/// This function requests permission to read and/or write to a specific
/// `HKObjectType`.
/// - Parameter completion: Completion handler must be able to handle boolean return.
func requestAuthorization(completion: @escaping (Bool) -> Void) {
    // Check if `HKHealthStore` is available to the user of the app.
    guard HKHealthStore.isHealthDataAvailable() else {
        completion(false)
        return
    }

    // Check if category type `.sexualActivity` is available to the user.
    guard let sexualActivityType = HKObjectType.categoryType(forIdentifier: .sexualActivity) else {
        completion(false)
        return
    }

    // Create a set containing the category types we'd like to access.
    let writeTypes: Set = [
        sexualActivityType
    ]

    // Finally request authorization.
    HKHealthStore().requestAuthorization(toShare: writeTypes, read: nil) {
        (success, _) in
        completion(success)
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Сохранить образец

/// This function saves a new sample to `HKHealthStore`. It adds all neccessary meta date.
/// - Parameters:
///   - protection: Was protection used?
///   - date: When was the date of sexual acitivty?
///   - identifier: A UUID that allows to delete the sample later.
///   - completion: Completion handler must be able to handle boolean return.
func saveSample(with protection: Bool, date: Date, identifier: UUID, completion: @escaping (Bool) -> Void) {
    // Check if category type `.sexualActivity` is available to the user.
    guard let sexualActivityType = HKObjectType.categoryType(forIdentifier: .sexualActivity) else {
        completion(false)
        return
    }

    /**
     Create the sample.
     `value` must be 0. Otherwise the app will crash.
     `metadata` must contain all three keys. `HKMetadataKeySyncIdentifier` requires `HKMetadataKeySyncVersion`. Version number is 
     */
    let sample = HKCategorySample(
        type: sexualActivityType,
        value: 0,
        start: date,
        end: date,
        metadata: [
            HKMetadataKeySexualActivityProtectionUsed: protectionUsed,
            HKMetadataKeySyncIdentifier: identifier.uuidString,
            HKMetadataKeySyncVersion: 1
        ]
    )

    HKHealthStore().save(sample) { (success, error) in
        completion(success)
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима

Удалить объект

/// Deletes the sample with the specified identifier.
/// - Parameters:
///   - identifier: The UUID used to save the sample.
///   - completion: Completion handler must be able to handle boolean return.
func deleteObject(identifier: UUID, completion: @escaping (Bool) -> Void) {
    // Narrow down the possible results.
    let predicate = HKQuery.predicateForObjects(
        withMetadataKey: HKMetadataKeySyncIdentifier,
        allowedValues: [identifier.uuidString]
    )

    // Delete all the objects that match the predicate, which should only be one.
    HKHealthStore().deleteObjects(of: HKCategoryType(.sexualActivity), predicate: predicate) { success, _, error in
        completion(success)
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Изменение образца

Вам придется удалить старый объект и сохранить новый образец.

Оцените статью
devanswers.ru
Добавить комментарий