2
3

【SwiftUI】ウィジェットを強制的に更新する

Posted at

はじめに

アプリ側でウィジェットの着せ替えを設定できる仕組みを作った際に、
着せ替えを変更したタイミングで即時にウィジェットに反映されないと「変更されないじゃん」と思われてしまう可能性が高いです。
それを防ぐためにアプリ側で強制的に更新させたいです。

今回はその方法を記事にしました。

実装

アプリ側で絵文字を設定するとウィジェットに表示される絵文字も変更されるというアプリで考えます。
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")

公式ドキュメント

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3