Learning Widgets, I try a simple pattern:
Widget has No "included Configuration Intent".
It compiles and works. Widget is updated every 5 minutes as asked line 23 (final snippet).
But the message is never updated (line 48 of final snippet) with globalToPass (as expected from line 24): it always shows "Hello".
What I tried:
Problem : Widget never updated its message field
Probably I need to have the message in @State var, but I could not get it work.
get a textField in the app;
have the Widget updated when textField is changed.
Widget has No "included Configuration Intent".
It compiles and works. Widget is updated every 5 minutes as asked line 23 (final snippet).
But the message is never updated (line 48 of final snippet) with globalToPass (as expected from line 24): it always shows "Hello".
What I tried:
Create a singleton to hold the data to pass:
Code Block class Util { class var shared : Util { struct Singleton { static let instance = Util() } return Singleton.instance; } var globalToPass = "Hello" }
shared the file between the 2 targets App and WidgetExtension
In VC, update the singleton when textField is changed and ask for widget to reload timeline
Code Block @IBAction func updateMessage(_ sender: UITextField) { Util.shared.globalToPass = valueToPassLabel.text ?? "--" WidgetCenter.shared.reloadTimelines(ofKind: "WidgetForTest") WidgetCenter.shared.reloadAllTimelines() }
Problem : Widget never updated its message field
Probably I need to have the message in @State var, but I could not get it work.
Here is the full widget code at this time:
Code Block import WidgetKit import SwiftUI struct LoadStatusProvider: TimelineProvider { func placeholder(in context: Context) -> SimpleEntry { SimpleEntry(date: Date(), loadEntry: 0, message: Util.shared.globalToPass) } func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { let entry = SimpleEntry(date: Date(), loadEntry: 0, message: Util.shared.globalToPass) completion(entry) } func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) { var entries: [SimpleEntry] = [] // Generate a timeline consisting of five entries an hour apart, starting from the current date. let currentDate = Date() for minuteOffset in 0 ..< 2 { let entryDate = Calendar.current.date(byAdding: .minute, value: 5*minuteOffset, to: currentDate)! let entry = SimpleEntry(date: entryDate, loadEntry: minuteOffset, message: Util.shared.globalToPass) entries.append(entry) } let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) } } struct SimpleEntry: TimelineEntry { let date: Date let loadEntry: Int let message: String } struct WidgetForTestNoIntentEntryView : View { var entry: LoadStatusProvider.Entry var body: some View { let formatter = DateFormatter() formatter.timeStyle = .medium let dateString = formatter.string(from: entry.date) return VStack { Text(String(entry.message)) HStack { Text("Started") Text(entry.date, style: .time) } HStack { Text("Now") Text(dateString) } HStack { Text("Loaded") Text(String(entry.loadEntry)) } } } } @main struct WidgetForTestNoIntent: Widget { let kind: String = "WidgetForTestNoIntent" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: LoadStatusProvider()) { entry in WidgetForTestNoIntentEntryView(entry: entry) } .configurationDisplayName("My Widget") .description("This is an example widget.") } } struct WidgetForTestNoIntent_Previews: PreviewProvider { static var previews: some View { WidgetForTestNoIntentEntryView(entry: SimpleEntry(date: Date(), loadEntry: 0, message: "-")) .previewContext(WidgetPreviewContext(family: .systemSmall)) } }
I have not defined extension for IntentHandler
You pretty much have to. I use:
Note: you have to set up a shared group between the app and the widget in the capabilities of the targets.
Code Block import UIKit import WidgetKit ... //code //code for widget UDM.shared.UserDefaults(suiteName: "group.whatever")?.setValue(urCode, forKey: "I'm a key") WidgetCenter.shared.reloadAllTimelines()
Note: you have to set up a shared group between the app and the widget in the capabilities of the targets.