写真ライブラリへのアクセス(PHPicker)で記録に写真を添付できるようになったので、以前実装したウィジェットにも最新の記録内容を表示させたくなり、App Groupsでのデータ共有に挑戦しました。
1. 通常のUserDefaultsで共有できると思い込んでいた
最初、本体アプリで保存しているUserDefaults.standardの値を、そのままウィジェット側からも読み込めるものだと思い込んでいました。
UserDefaults.standard.set(count, forKey: "latestCount")
実際には本体アプリとウィジェットはそれぞれ別のサンドボックス(プロセス)で動作しており、UserDefaults.standardはアプリごとに独立しています。素直に保存しただけではウィジェット側から値が見えず、なぜ反映されないのか原因調査に時間がかかりました。
2. App Group IDの設定を両方のターゲットに追加し忘れていた
App Groupsという仕組みを使えば共有できると分かり設定を始めたのですが、本体アプリのターゲットにだけApp Group IDを追加し、ウィジェットのExtensionターゲット側への追加を忘れていました。
Signing & Capabilities → App Groups →
group.com.example.myapp のようなIDを追加
両方のターゲットにこのCapabilityとApp Group IDを追加する必要があります。片方だけだとビルドは通ってしまうため、実行するまで設定漏れに気づきにくいのが厄介でした。
3. 共有UserDefaultsのキー名を書き間違えていた
App Group IDを両方に設定したあとも値が共有されず悩んだのですが、原因は単純な書き間違いでした。
UserDefaults(suiteName: "group.com.example.myapp")
本体アプリ側とウィジェット側で、このsuiteNameの文字列に微妙な差異(末尾のタイプミス)があり、別々のグループとして扱われていました。文字列をどこか1箇所の定数にまとめて両ターゲットから参照するようにしたところ、この手の食い違いが起きなくなりました。
4. データを更新してもウィジェットがすぐに反映されなかった
共有データの読み書きはできるようになったものの、本体アプリでデータを更新してもウィジェットの表示がすぐには変わらないことに戸惑いました。
ウィジェットは決まったタイミングでしか再描画されない仕組みのため、データ更新後に明示的な再読み込みリクエストを送る必要がありました。
WidgetCenter.shared.reloadAllTimelines()
本体アプリでデータを保存した直後にこの一行を呼ぶことで、ウィジェットの表示が即座に更新されるようになりました。
まとめ
- 本体アプリとウィジェットは別プロセスのため、通常の
UserDefaults.standardはそのままでは共有されない - App Group IDは本体・ウィジェットの両方のターゲットに設定する必要がある
- 共有用の
suiteName文字列は1箇所の定数にまとめ、タイプミスによる食い違いを防ぐ - データ更新後は
WidgetCenter.shared.reloadAllTimelines()を呼ばないとウィジェットの表示は自動的には更新されない
見た目には地味な機能ですが、プロセスをまたいだデータ共有という個人開発ではあまり触れてこなかった領域で、つまずきどころが多い実装でした。
本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。


コメント