はじめに
アプリ側でウィジェットの着せ替えを設定できる仕組みを作った際に、
着せ替えを変更したタイミングで即時にウィジェットに反映されないと「変更されないじゃん」と思われてしまう可能性が高いです。
それを防ぐためにアプリ側で強制的に更新させたいです。
今回はその方法を記事にしました。
実装
アプリ側で絵文字を設定するとウィジェットに表示される絵文字も変更されるというアプリで考えます。
emoji
を@AppStorage
で持ってAppGroupで共有しています。
これでウィジェット側でもemoji
を使えるようになります。
import SwiftUI
struct ContentView: View {
@AppStorage("emoji", store: UserDefaults(suiteName: "group.com.demo")) var emoji: String = "❔"
private let emojis = ["🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐻❄️", "🐨", "🐯", "🦁", "🐮", "🐷", "🐸", "🐵"]
var body: some View {
VStack {
Text(emoji)
Button {
emoji = emojis.randomElement()!
} label: {
Text("絵文字変更")
}
}
.padding()
}
}
ただ、上記のコードでは変更がウィジェットのほうで即時反映されません。
そこで、ボタンを押したタイミングでウィジェットに更新リクエストを送ります。
import SwiftUI
import WidgetKit
struct ContentView: View {
@AppStorage("emoji", store: UserDefaults(suiteName: "group.com.demo")) var emoji: String = "❔"
private let emojis = ["🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐻❄️", "🐨", "🐯", "🦁", "🐮", "🐷", "🐸", "🐵"]
var body: some View {
VStack {
Text(emoji)
Button {
emoji = emojis.randomElement()!
+ WidgetCenter.shared.reloadAllTimelines()
} label: {
Text("絵文字変更")
}
}
.padding()
}
}
ウィジェットを複数ターゲットで用意している場合、上記のコードを使用するとすべてのウィジェットが更新されてしまします。
特定のウィジェットターゲットだけ更新したい場合は、以下のようにバンドルIDを指定してください。
WidgetCenter.shared.reloadTimelines(ofKind: "com.demo.demo-widget")
公式ドキュメント