【Swift】ヘルスケア連携でHKWorkoutのアクティビティの名前を日本語で取得する

公開日: 

はじめに

iOS のヘルスケアと連携したアプリを作っていて、ワークアウトをヘルスケアアプリから取得してきたときに「ワークアウトのアクティビティの名前を取得したい!」という状況があったので、備忘録として残します。

HKWorkout クラス

ヘルスケアアプリからワークアウトを取得すると、HKWorkoutクラスで値が返ってきます。ワークアウトを取得する方法は今回は割愛します。詳しくは、以下の記事を参考にしてください。

https://qiita.com/mag-chang/items/e0f39b8c4794b71d858d

HKWorkout クラスにはワークアウトに関する様々な情報が格納されています。

HKWorkout.swift
var workout: HKWorkout // ヘルスケアから取得してきたHKWorkoutクラス

print(workout.uuid) // uuid
print(workout.totalEnergyBurned) // 消費したエネルギー
print(workout.duration) // 持続時間
print(workout.startDate) // 開始時刻
print(workout.endDate) // 終了時刻

例えば、ワークアウトのuuid、開始時刻、終了時刻、消費カロリーなどが取得できます。そしてこのクラスにはworkoutActivityTypeというプロパティがあり、このプロパティからアクティビティの名前が取得できると思いきや...

sample
print(workout.workoutActivityType.rawValue) // 何やら数字しか取得できない

取り出せるのは何やら数字のみ。『ランニング』とか『running』みたいなのが取り出せると思ったのに...

workoutActivityType プロパティ

このプロパティについて調べてみるとHKWorkoutActivityTypeという列挙型で何やらたくさんのアクティビティを含んでるっぽい。そしてなんとその列挙型の中には、アクティビティ名のプロパティがない!いや、なんで!? 結論、このままではrawValueIntしか取得できません

アクティビティ名の取得

いろいろ調べていると、

https://stackoverflow.com/questions/30175237/how-to-get-the-name-of-hkworkoutactivitytype-in-healthkit

取得できないなら、extension で取得できるようにすればいいじゃない。というのがこの記事の内容。確かに。ということで、この記事を参考に日本語版を作成してみました。

以下のコードはiOS 15.1時点のものです。それ以降のバージョンでは、アクティビティの種類が変更されている可能性があります。

extension.swift
import HealthKit

extension HKWorkoutActivityType {
    var name: String {
        switch self {
        case .americanFootball:             return "アメリカンフットボール"
        case .archery:                      return "アーチェリー"
        case .australianFootball:           return "オーストラリアンフットボール"
        case .badminton:                    return "バドミントン"
        case .baseball:                     return "野球"
        case .basketball:                   return "バスケットボール"
        case .bowling:                      return "ボウリング"
        case .boxing:                       return "ボクシング"
        case .climbing:                     return "クライミング"
        case .crossTraining:                return "クロストレーニング"
        case .curling:                      return "カーリング"
        case .cycling:                      return "サイクリング"
        //        case .dance:                        return "dance" // deprecated
        //        case .danceInspiredTraining:        return "Dance Inspired Training" // deprecated
        case .elliptical:                   return "エリプティカル"
        case .equestrianSports:             return "乗馬関連スポーツ"
        case .fencing:                      return "フェンシング"
        case .fishing:                      return "釣り"
        case .functionalStrengthTraining:   return "機能的筋力トレーニング"
        case .golf:                         return "ゴルフ"
        case .gymnastics:                   return "体操競技"
        case .handball:                     return "ハンドボール"
        case .hiking:                       return "ハイキング"
        case .hockey:                       return "ホッケー"
        case .hunting:                      return "ハンティング"
        case .lacrosse:                     return "ラクロス"
        case .martialArts:                  return "マーシャルアーツ"
        case .mindAndBody:                  return "マインドアンドボディ"
        //        case .mixedMetabolicCardioTraining: return "Mixed Metabolic Cardio Training" // deprecated
        case .paddleSports:                 return "パドルスポーツ"
        case .play:                         return "遊び"
        case .preparationAndRecovery:       return "準備と回復"
        case .racquetball:                  return "ラケットボール"
        case .rowing:                       return "ローイング"
        case .rugby:                        return "ラグビー"
        case .running:                      return "ランニング"
        case .sailing:                      return "セーリング"
        case .skatingSports:                return "スケート"
        case .snowSports:                   return "ウインタースポーツ"
        case .soccer:                       return "サッカー"
        case .softball:                     return "ソフトボール"
        case .squash:                       return "スカッシュ"
        case .stairClimbing:                return "ステアステッパー"
        case .surfingSports:                return "サーフィン"
        case .swimming:                     return "水泳"
        case .tableTennis:                  return "卓球"
        case .tennis:                       return "テニス"
        case .trackAndField:                return "陸上競技"
        case .traditionalStrengthTraining:  return "伝統的筋力トレーニング"
        case .volleyball:                   return "バレーボール"
        case .walking:                      return "ウォーキング"
        case .waterFitness:                 return "ウォーターフィットネス"
        case .waterPolo:                    return "水球"
        case .waterSports:                  return "ウォータースポーツ"
        case .wrestling:                    return "レスリング"
        case .yoga:                         return "ヨガ"

        // iOS 10
        case .barre:                        return "バレエ"
        case .coreTraining:                 return "コアトレーニング"
        case .crossCountrySkiing:           return "クロスカントリースキー"
        case .downhillSkiing:               return "ダウンヒルスキー"
        case .flexibility:                  return "柔軟体操"
        case .highIntensityIntervalTraining:    return "高強度インターバルトレーニング"
        case .jumpRope:                     return "縄跳び"
        case .kickboxing:                   return "キックボクシング"
        case .pilates:                      return "ピラティス"
        case .snowboarding:                 return "スノーボード"
        case .stairs:                       return "階段昇降"
        case .stepTraining:                 return "ステップトレーニング"
        case .wheelchairWalkPace:           return "車椅子ペースウォーキング"
        case .wheelchairRunPace:            return "車椅子ペースランニング"

        // iOS 11
        case .taiChi:                       return "太極拳"
        case .mixedCardio:                  return "複合カーディオトレーニング"
        case .handCycling:                  return "ハンドサイクリング"

        // iOS 13
        case .discSports:                   return "フライングディスクスポーツ"
        case .fitnessGaming:                return "フィットネスゲーム"

        case .cricket:                      return "クリケット"
        case .cardioDance:                  return "ダンス"
        case .socialDance:                  return "社交ダンス"
        case .pickleball:                   return "ピックルボール"
        case .cooldown:                     return "クールダウン"
        case .other:                        return "その他"

        default:                            return "その他"
        }
    }
}

いくつか、非推奨になっているものがあったり、iOS のアップデートで適宜追加されているようなので新しいアクティビティが追加されたりしたらこのファイルの修正が必要ですね。一応、これでアクティビティ名が日本語で取得できるようになりました!

result
print(workout.workoutActivityType.name) // 『ランニング』とか『水泳』とか

まとめ

少しめんどくさいですが、ヘルスケアアプリから取得してきたデータを解析して、アクティビティの名前を日本語で取得したい場合は、上のファイルをコピペしましょう。

せめて英語でもいいからアクティビティ名はあってほしかった。てか普通になんでないねん。少し力づくなところはありましたが、取得できてよかったです。特に内容とは関係ないんですが、めちゃめちゃ多くのアクティビティがあっておもろいですね。

では、Bye