記事の内容
- アプリ内のボタンをタップしたら、ウィジェットを更新する
この記事で記載しないこと
- 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
参考資料