権熙哲(クォン・フィチョル)

プロジェクト一覧

iOS

Insulin Note

インスリン投与記録の入力を5ステップから1ステップに減らしたiOSウィジェットアプリ

期間:
2024.07.15 ~ 2026.04.26
担当:
個人開発
SwiftSwiftUISwiftDataWidgetKitAppIntents
5 → 1ステップ
投与記録の導線
26件
App Storeダウンロード

2026-09-27時点

iOS 17+
対応バージョン
個人開発
企画から公開まで

背景とユーザー課題

私は1型糖尿病で、持効型と速効型のインスリンを投与しています。持効型は夜10時から11時ごろに打ちますが、就寝はその後になるため、「今日はすでに投与したか」が曖昧になることがありました。投与忘れだけでなく、記憶だけを頼りにした重複投与も避ける必要があります。

既存のCGMアプリにも投与記録はありましたが、起動から保存まで5ステップ以上必要でした。毎日繰り返す行動では、この小さな負担が記録の中断につながります。そこで機能の多い健康管理アプリではなく、必要な瞬間に最も近いホーム画面とロック画面から一度で記録できる体験を目標にしました。

設計と技術選定

アプリ、ホーム画面ウィジェット、ロック画面ウィジェットが同じ投与記録を参照する必要がありました。SwiftDataをローカルストアとし、App Groupで共有します。WidgetKitとAppIntentsにより、アプリを開かずに記録と確認ができます。

  1. 01ホーム・ロック画面投与状況と直近時刻を確認
  2. 02AppIntentウィジェットから記録を依頼
  3. 03ModelActorCRUDを一つの実行コンテキストで直列化
  4. 04SwiftDataApp Groupの共有ストアへ保存
  5. 05WidgetKitタイムラインを更新して反映
投与記録がアプリとウィジェットへ反映される流れ

SwiftDataは高速な端末内記録と将来のiCloud連携を考えて選びました。iOS 17以上を下限にしたのも、SwiftDataとインタラクティブウィジェットに必要なAppIntentsを利用するためです。データアクセスは実際の同期不具合とSwift 6移行を経て、共有コンテキストからModelActor中心の構造へ改善しました。

画面側はViewとModelだけで構成するMVパターンです。Viewはユーザー操作を受けてModelActorへ依頼するだけで、変更されたModelがViewの状態を更新する一方向の流れです。

UserからView、ModelActor、Modelを経てViewへ戻るMVパターンの構成図
MVパターン: Viewの依頼はModelActorを通してModelを変更し、変更されたModelがViewを再描画します。
ロック画面ウィジェット、メイン画面の記録・設定シート、カレンダーの記録修正画面が、それぞれSwiftDataのInsulinRecordとInsulinSettingに保存される流れの図
画面遷移: ロック画面ウィジェット、メイン画面の記録シート、カレンダーで修正した記録は、すべてSwiftDataのInsulinRecord・InsulinSettingに保存されます。

主な体験と機能

メイン画面では持効型・速効型インスリンを記録し、誤入力を修正・削除できます。初回起動時に基本設定を生成し、すぐに使い始められるようにしました。

  • メイン画面で持効型インスリンの投与量を選んで記録し、持効型と速効型の記録の投与量と時刻を修正する場面
    メイン画面
  • カレンダーで日付をタップしてその日の記録を開き、服薬率と曜日別の速効型投与パターンチャートを切り替える場面
    カレンダー画面
  • ホーム画面の持効型・速効型ウィジェットのボタンをタップし、アプリを開かずに記録すると投与時刻が表示される場面
    ホーム画面ウィジェットで記録
  • ロック画面ウィジェットのボタンで投与を記録すると、記録なしが投与時刻に変わる場面
    ロック画面ウィジェットで記録
実際のアプリ画面の録画です。横にスクロールして見られます。

カレンダーは単なる履歴ではなく、生活パターンを振り返る画面に拡張しました。投与日、服薬率、平均投与時刻に加え、速効型は時間と投与量の傾向をチャートで確認できます。ホーム画面から素早く記録し、ロック画面で直近時刻を確認することで、アプリを開く回数を減らしています。

  • 持効型・速効型の記録、修正、削除
  • 投与日・服薬率・平均時刻を示すカレンダーとダッシュボード
  • 速効型の時間・投与量パターンと継続記録の動機づけ
  • ホーム画面からのクイック記録、ロック画面での直近時刻確認

問題解決

主要な文脈はそのまま読めるようにし、実装の詳細は必要な項目だけ展開できる形に整理しました。

アプリとウィジェットの記録が同期されない
問題
Interactive Widgetで追加した投与が、本体アプリのUIと実ストアに反映されませんでした。
原因
AppIntentはView階層ではないため環境のModelContextを受け取れず、別コンテキストを作成していました。さらにsaveの呼び出しが抜け、変更がメモリ上にだけ残っていました。
解決
両方が同じコンテキストを参照し、保存を明示しました。Swift 6移行後はデータ競合を避けるため、CRUDをModelActor内へ移しました。
結果
アクセスをActorの実行コンテキストで直列化しました。Task内でモデルが解放されるクラッシュは、必要な値を事前にコピーして渡すことで解消しました。
View階層の責務とデータフローが複雑化
問題
RecordView、インスリン別の子View、投与量シートがBindingとクロージャで絡み合っていました。
原因
子Viewが表示だけでなく、シートに渡すビジネスロジックと既定投与量まで把握していました。
解決
状態と主要ロジックを親Viewへ集約し、子Viewは受け取ったデータの描画とクロージャ呼び出しだけを行う単方向のMV構造へ変更しました。
結果
Bindingの連鎖を減らし、機能追加時の確認範囲と副作用の可能性を抑えました。
記録はできても継続利用しにくいUI
問題
初期版は枠線中心の粗いUIで、修正・削除がありませんでした。カレンダーは投与有無だけを示し、独立した設定タブも役割が小さい状態でした。
原因
持効型の記録というMVPに集中し、誤入力や速効型を続けて記録する動機まで考慮できていませんでした。
解決
修正・削除を追加し、設定をメイン画面へ統合しました。カレンダー下には服薬の一貫性と速効型の傾向を示すダッシュボードとストリークを置きました。
結果
狭い画面の情報構造を簡潔にし、自分の生活パターンを確認することが継続記録の理由になるよう設計しました。

成果と振り返り

ロック画面で記録を確認してから投与する個人のルーティンができ、「今日打ったか分からない」という不安を減らせました。2026年9月27日時点でApp Storeのダウンロードは26件です。大きな数字ではありませんが、自分の課題から始めた機能を公開・運用できる製品まで完成させました。

この開発で学んだのは、機能数よりも反復行動の摩擦とデータへの信頼が先にあるということです。次のアップデート(1.2)では、次の内容を準備しています。

  • HealthKit連携: 投与記録をヘルスケアアプリに保存し、CGMアプリが記録した血糖値を取り込んで、どんな状況でどれだけ投与したかを振り返れる指標を提供します。
  • ローカライズ: 少なくとも英語と日本語に対応します。
  • コード整理: メソッドが増えたModelActorを役割ごとのファイルに分けます。
  • テスト: Swift Testingで主要ロジックを検証します。
  • 不具合修正: メイン画面で記録を修正しても、すぐ画面に反映されない問題を直します。
Insulin Noteのメイン画面