0
2

More than 1 year has passed since last update.

[SwiftUI / WidgetKit]アプリのボタンをタップしたら、ウィジェットを更新する

Last updated at Posted at 2022-07-18

記事の内容

  • アプリ内のボタンをタップしたら、ウィジェットを更新する

この記事で記載しないこと

  • App Group の設定
  • UserDefaults の使用方法

開発環境

項目 内容
PC MacBook Air (2020 M1)
言語 Swift
フレームワーク SwiftUI
IDE Xcode
コード管理 GitHub

前提条件

  • App Group は、group.sample.Emojis で設定している

コード

ContentView.swift
import SwiftUI
import WidgetKit

struct ContentView: View {
    
    let emojis = [
        Emoji(icon: "😃", name: "大きい目の笑顔", description: "Grinning face with big eyes"),
        Emoji(icon: "🏂", name: "スノーボーダー", description: "Snowboarder"),
        Emoji(icon: "🦄", name: "ユニコーン", description: "Unicorn")
    ]
    
    var body: some View {
        VStack(alignment: .leading,spacing: 30){
            ForEach(emojis){ emoji in
                EmojiView(emoji: emoji)
                    .onTapGesture {
                        save(emoji)
                        WidgetCenter.shared.reloadAllTimelines()
                    }
            }
        }
    }
    
    private func save(_ emoji: Emoji){
        let userDefaults = UserDefaults(suiteName: "group.sample.Emojis")!
        guard let emojiData = try? JSONEncoder().encode(emoji) else { return }
        userDefaults.set(emojiData, forKey: "Emoji")
        print("saved Emoji: \(emoji)")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
EmojiView.swift
import SwiftUI

struct EmojiView: View {
    let emoji: Emoji
    var body: some View {
        Text(emoji.icon)
            .font(.largeTitle)
            .padding()
            .background(Color.purple)
            .clipShape(Circle())
    }
}

struct EmojiView_Previews: PreviewProvider {
    static var previews: some View {
        EmojiView(emoji: Emoji(icon: "🦄", name: "ユニコーン", description: "Unicorn"))
    }
}
EmojisWidget.swift
import WidgetKit
import SwiftUI

struct Provider: TimelineProvider {
    
    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
        let entry = SimpleEntry(date: Date(), emoji: Emoji(icon: "💛", name: "N/A", description: "N/A"))
        completion(entry)
    }
    
    func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
        let userDefaults = UserDefaults(suiteName: "group.sample.Emojis")!
        let date = Date()
        let emojiData = userDefaults.object(forKey: "Emoji") ?? Data()
        guard let emoji = try? JSONDecoder().decode(Emoji.self,from: emojiData as! Data) else {
            let entry = SimpleEntry(date: date, emoji: Emoji(icon: "💛", name: "N/A", description: "N/A"))
            let timeline = Timeline(entries: [entry], policy: .never)
            completion(timeline)
            return
        }
        let entry = SimpleEntry(date: date, emoji: emoji)
        let timeline = Timeline(entries: [entry], policy: .never)
        completion(timeline)
    }
    
    func placeholder(in context: Context) -> SimpleEntry {
        return SimpleEntry(date: Date(), emoji: Emoji(icon: "💛", name: "N/A", description: "N/A"))
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let emoji: Emoji
}

struct EmojisWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        VStack {
            EmojiView(emoji: entry.emoji)
            Text(entry.emoji.description)
                .font(.subheadline)
                .foregroundColor(.gray)
        }
    }
}

@main
struct EmojisWidget: Widget {
    let kind: String = "EmojisWidget"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: "Emojis_Widget", provider: Provider()) { entry in
            EmojisWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Emojis Widget")
        .description("This is an example widget.")
    }
}

struct EmojisWidget_Previews: PreviewProvider {
    static var previews: some View {
        EmojisWidgetEntryView(entry: SimpleEntry(date: Date(), emoji: Emoji(icon: "💛", name: "N/A", description: "N/A")))
            .previewContext(WidgetPreviewContext(family: .systemSmall))
    }
}

GitHub

参考資料

0
2
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
0
2