お父さん体重記録帳アプリからヘルスケアアプリに体重計を移行してみた

## はじめに

昔iPhone4s時代であろうか、体重の記録にソフトバンクからリリースされている[お父さん体重記録帳](https://www.softbank.jp/mobile/service/otosan-app/)というアプリで体重計で測定した結果を記録していました。

![PNGイメージ.png](https://qiita-image-store.s3.amazonaws.com/0/42735/c96f7be5-e6b6-da0c-64ce-d66515c1e8b0.png)

それから時は過ぎてHealthKitができ、Bluetooth連携の体重計に買い替えヘルスケアアプリに体重の記録をするようになりましたが、過去に記録を見るためだけにお父さん体重記録帳をアンインストールできない状況が数年続いています。

アプリの断捨離のために、移行することができないか考えました。

## エクスポートする

お父さん体重記録帳アプリはエクスポートできることがわかりました。

![otosan_app01.png](https://qiita-image-store.s3.amazonaws.com/0/42735/0f44cadd-c35a-4336-3c33-74d0f846013c.png)

ファイルに保存でiCloudドライブ経由でmacにエクスポートしてみました。

## エクスポートしたファイルの中身

<img width="395" alt="スクリーンショット 2019-03-11 16.31.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/42735/e71416db-fde0-2ff8-2e5d-e9eadb80654d.png">

**database.weightlog** というファイルが出力されます。
plist形式のファイルのようです。
ArrayとDictionaryの形式になっており、**date** と **weight** という２つキーで値が格納されていることがわかります。

## ファイルを読み込み値を取得するようにする

今回は、プロジェクト内にこのdatabase.weightlogをインポートします。

まずデータを格納するweightクラスを作りました。
格納時に、日付は文字列からDate型の変換します。体重も文字列からDouble型にキャストするようにしました。

```swift
class weight: NSObject {
    var date:Date?
    var value:Double?
    
    init(date:String , value:String) {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy/MM/dd"
        formatter.locale = Locale(identifier: "ja_JP")
        self.date = formatter.date(from: date)
        self.value = Double(value)
    }
}
```
次にファイルを読み込み格納してみます。

まずは格納するための配列を作成します。

```swift
    private var weightArray:[weight] = []
```

ファイルを読み込みweightクラス形式で格納します。

```swift
        if let path = Bundle.main.path(forResource: "database", ofType:"weightlog" ) {
            if let dictArray = NSArray(contentsOfFile: path) {
                for item in dictArray {
                    if let dict = item as? NSDictionary {
                        let d = dict["date"] as! String
                        let w = dict["weight"] as! String
                        let value = weight(date: d, value: w)
                        weightArray.append(value)
                    }
                }
            }
        }
```

## HealthKitに登録する

## 準備

プロジェクト設定でHealthKitをONにします。

<img width="732" alt="スクリーンショット 2019-03-11 16.53.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/42735/0a8c2660-2892-256c-84b9-bd0ef951a9ed.png">

### パーミッションの取得

まずHealthKitを使うにはアクセスするために許可が必要です。

許可を得る理由をInfo.plistに記載します。

<img width="641" alt="スクリーンショット 2019-03-11 16.41.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/42735/cac2b9bf-a22b-703f-8fa5-a4bb6c2c1c4d.png">

次に、許可を得ます。読み込みは今回は必要ありませんが、体重の情報を意味している`.bodyMass`を指定しています。

```swift

    private func requestAuthorization() {
        // 書き込みを許可する型.
        let typeOfWrites: Set<HKSampleType> = [HKSampleType.quantityType(forIdentifier: .bodyMass)!]
        // 読み込みを許可する型.
        let typeOfReads: Set<HKSampleType> = [HKSampleType.quantityType(forIdentifier: .bodyMass)!]

        //  HealthStoreへのアクセス承認をおこなう.
        myHealthStore.requestAuthorization(toShare: typeOfWrites, read: typeOfReads, completion: { (success, error) in
            if let e = error {
                print("Error: \(e.localizedDescription)")
                return
            }
            print(success ? "Success!" : " Failure!")
        })
    }
```

### 体重データをHealthKitに登録する

実際にエクスポートした体重情報を登録します。
Arrayから取り出し、１件づつ登録していきます。

```swift
    @IBAction func writeButtonAction(_ sender: Any) {
        for w in weightArray {
            writeData(weight: w.value!, date: w.date!)
        }
    }
```

```swift
    private func writeData(weight: Double , date:Date) {
        // 体重のタイプ.
        let typeOfWeight = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)
        // 体重データを作成(Kg->gに変換する).
        let myWeight = HKQuantity(unit: HKUnit.gram(), doubleValue: weight * 1000)
        // StoreKit保存用データを作成.
        let myWeightData = HKQuantitySample(type: typeOfWeight!, quantity: myWeight, start: date, end: date)
        
        // データの保存.
        myHealthStore.save(myWeightData, withCompletion: { (success, error) in
            if let e = error {
                print("Error: \(e.localizedDescription)")
            }
            print(success ? "Success!" : " Failure!")
        })
    }
```

## 最後に

色々なサイトを参考に登録までしました。
元のデータが日付のみで時刻がないので当日の0:00にして登録しています。

ソースコード一式は、[Github](https://github.com/FromF/healthKitWeight)に公開してありますので参考にしてください。

簡単でありますが、以上となります。

## 参考サイト

下記のサイトを参考にさせていただきました。ありがとうございました。

* [体重データのHealthStoreへの読み書き](http://docs.fabo.io/swift/healthkit/002_healthkit.html)
* [plistからデータを読み込む swift 3.0](https://qiita.com/Saayaman/items/1f1da4abab61b7465a13)
* [【Swift】Dateの王道 【日付】](https://qiita.com/rinov/items/bff12e9ea1251e895306)
* [[Apple Watch] 30分で作るヘルスケアWatchOS App](https://qiita.com/sato-shin/items/1a6859d854b754fff85b)