はじめに
この記事の概要
iOS 17以降で利用できるAppIntentを活用し、Widgetに編集用のプルダウン選択肢を表示する方法を解説します。選択肢にはユーザー設定(UserDefaults)から取得したデータを使用し、動的に反映させる方法を具体的なコード例とともに紹介します。
AppIntentで選択肢付きWidgetを作成する手順
Widgetの作成とIntent対応設定
Widget Extensionで「AppIntent」を選択
Widgetを作成する際に、「Include Configuration Intent(AppIntent)」にチェックを入れることで、初期構成ファイル ConfigurationAppIntent が自動生成されます。
@ParameterにoptionsProviderを使ってプルダウンを実現
DynamicOptionsProviderの活用
コード例:プルダウンを表示するAppIntentの設定
AppIntentで選択肢を表示するには、@ParameterにoptionsProviderを指定し、選択肢を返すクラス(DynamicOptionsProvider準拠)を実装します。
@Parameter(
title: "Favorite Team",
optionsProvider: TeamNamesOptionsProvider()
)
var favoriteTeam: String?
TeamNamesOptionsProviderは以下のように定義します。
private struct TeamNamesOptionsProvider: DynamicOptionsProvider {
func results() async throws -> [String] {
return Teams.createTeamLongNMList()
}
}
Shared UserDefaultsから選択肢データを取得する方法
AppとWidget間でのデータ共有
SharedDefaultsを使ったJSONデータの読み込み
final class Teams {
private static let sharedDefaults: UserDefaults = UserDefaults(suiteName: "group.scoreboardMobile.Widget")!
static func createTeamLongNMList() -> [String] {
let jsonString = sharedDefaults.string(forKey: "selected_teams") ?? "アプリで選択してください"
let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
do {
let teams = try decoder.decode([Team].self, from: jsonData)
return teams.map { $0.teamLongNM }
} catch {
print("Failed to decode JSON: \(error)")
return []
}
}
}
注意点:DynamicOptionsProviderはStaticで呼ぶ
Staticでないと値を取得できない理由
optionsProviderがDynamicOptionsProviderのインスタンスを直接受け取る仕様のため、内部で参照するメソッドやプロパティもすべてstaticである必要があります。UserDefaultsからのデータ取得もstatic経由で行うことで、Widgetから正しく選択肢を表示できます。

読者
なんでstaticじゃないと動かないんですか?

ごりら
仕様上の制限で、インスタンスメソッドだとWidgetから呼び出す際に適切に初期化されない可能性があるんだ。特にUserDefaultsアクセスはstaticが安全なんだよ。
まとめ
この記事の振り返り
- WidgetでAppIntentを使えば、編集UIにプルダウンを追加できる
@ParameterのoptionsProviderを活用し、動的な選択肢表示が可能- Shared UserDefaultsを使えば、アプリで設定した値をWidgetに反映できる
DynamicOptionsProviderの内部処理はstaticで構築するのが安全


コメント