Post

Replies

Boosts

Views

Activity

Reply to Xcode preview for Widget?
I am also having problems with getting Swift views to preview correctly. The error I am seeing is: ”Remote Human Readable Error: PreviewAgentError: Statically rendering previews is not supported on iOS Simulators” I don't have any problems at all with previews in small, toy apps, but inside my real, actual project views don't render. Widgets can generate previews most of the time, but plain, non-widget views will not ever render. I have to develop my views in a separate project and them copied them over to the main project once they are mostly done.
Jul ’20
Reply to I can not set my date to be updated in widgetKit
The .time and .date styles do not update over time. Using "Text(Date(), style: .time)" will display the time when the widget timeline was refreshed with a call to getTimeline(for:in:completion:) and will remain static until the next time the timeline is regenerated. The relative styles (.relative, .offset, .timer) are special in that they update in real-time between refreshes of the timeline which allows you to show a relative time without having to generate a timeline entry for each change in the value. As a side note, I will mention that .relative shows the difference in time but without any indication of if it is positive or negative. Exactly 15 minutes before the given time will return "15 min, 0 sec" and exactly 15 minutes after the given time will also return "15 min, 0 sec"
Aug ’20
Reply to WidgetKit & dark mode
Depending on what you want to do, you don't even have to do that. The simplest way to handle light/dark mode is to define any color you want switch in the asset catalog (something like "Assets.xcassets")and set "Appearances" for the color to "Any, Dark". You can do this for as many colors as you need. You can then use those colors by name using something like: Color("WidgetBackground"). The widget will then automatically switch when the system theme changes.
Aug ’20
Reply to Mismatch between widget size and @Environment value in TimelineProvider
The way that I am dealing with this is to generate the same array for all widgets and then limit it on the view side where the @Environment(\.widgetFamily) does work. In your case, you can have your timeline always generate 9 items in the array, then in your view you can do something like the following: func getArray(array: [String]) -> [String] { 	 if (family == .systemSmall) { 			return Array(array.prefix(3)) 	 } else if (family == .systemMedium) { 			return Array(array.prefix(6)) 	 } else { 			return array 	 } }
Aug ’20
Reply to Widgets refreshing continuously, non-stop, not respecting timeline
Everything looks correct in your code. It should be working as you expect. A single timeline entry is generated with a single random number and then after 15 minutes your timeline should be regenerated. As you update to beta 4, be aware that several of the things you have copied are now deprecated and I have found it acts a little strange with the old methods. The placeholder logic is now handled in a placeholder(in:) alongside snapshot and timeline, which have respectively been changed to getSnapshot(with:in:completion:) and getTimeline(with:in:completion:)
Aug ’20
Reply to WidgetKit refresh policy
Another thing to be aware of, is that the system has a floor to how frequently it will allow you to refresh the widget. I have no idea what all might go into the decision process but I did some testing with my widgets and on Beta 4 it seems like with a configured refresh rate of 5 seconds (this is way too short, never actually do this) the actual refresh rates is roughly every 5 minutes when the screen is active and the widget is visible or every 15 minutes with the phone screen turned off.
Aug ’20
Reply to Is there a way to know when widget is installed/uninstalled?
I don't know if you can get exactly what you are looking for, but I think you can achieve the same end results using getcurrentconfigurations(_:). It will allow you to query what widget configurations are currently in use from the main application. This should allow you to periodically poll for the current widgets and then record whatever you need. https://developer.apple.com/documentation/widgetkit/widgetcenter/getcurrentconfigurations(_:)
Aug ’20
Reply to Is there a way to know when widget is installed/uninstalled?
I haven't tried to use the API myself, but what you are seeing feels like a bug to me. I am certainly not from Apple so I don't know what they expect, but I would expect it to give you up-to-date information about all the currently active widgets along with a valid family type. If you aren't seeing that I would recommend submitting feedback and hope it gets addressed before the release.
Aug ’20
Reply to Widget does not render all the time
You are definitely not alone in seeing this issue. I am constantly struggling against it. Unfortunately, I also don't have any real solution for you. I have a few different widgets and I have done a far bit of testing to try to figure out what is going on. I can provide a few notes in case that helps you or anyone else get closer to a solution. The preview view is generated one time and then seems to be cached forever. Although I haven't tested this, I believe you would have to completely delete the app to get the preview to refresh. This is relevant because if you happen to have had a blank preview initially it will continue to be blank even if you have changed the preview since then. The less my widgets need to do while generating the timeline entries, the more likely they are to succeed. One widget is only pulling a few user configured values from the main application and it works nearly 100% of the time. Other widgets need to retrieve a significant amount of data from a database. Logging tells me that those widgets are always completing the timeline generation work, but then the data often just completely fails to show up in the widget itself. While the widget will appear blank if your extension crashes in some way, it does not appear to be the only reason it can be blank. I have seen it be blank many times without any sign that it had crashed and plenty of evidence to the contrary. For whatever it is worth, I am testing on a real device (iPhone X) and not the simulator.
Aug ’20
Reply to WidgetKit - custom dynamical intent - defaults?
For parameters that have a known set of options (boolean, String, enum, etc) you specify the default in the intent definition file when you specify the parameter in the first place. When a snapshot is generated for preview or when the user initially installs a widget on their homes screen, the default value is the way the intent is initialized, and that is the value you will receive in the configuration that is sent to your snapshot(...) and timeline(...) implementations. The one wrinkle here is that if the widget was installed using an older version of your app (ie you add a new configuration option in a later release) that value will not get initialized and will be nil until the user opens the configuration. I believe this is a bug (filed as FB8754457 if anyone at Apple is listening). The way to deal with that is to look for that nil value and replace it with whatever you want the default to be. I do this in an extension to the intent like the following: extension MyIntent {     public func me_showThing() -> Bool {         return self.showThing?.boolValue ?? true 		} } If you are trying to specify the default value for a dynamic parameter then you do that in the same place you specify the list of possible values. Once you specify that a parameter values are dynamic then a protocol is generated that is something like MyIntentHandling which has two relevant methods: one is for specifying all the options of the form provideMyThingOptionsCollectionForMyIntent:withCompletion: and one to specify the default that is something like defaultMyThingForMyIntent:
Oct ’20
Reply to iOS 14 widgets: Content update frequency and latency limits and best practices
I don't have any definitive answers here, but I can answer one of your questions: Always use multiple timeline entries if the exact timing of when a widget shows up is important. When you refresh your widget, if you add a timeline entry for a given date/time it will show up within a second or two of that time. On the other hand, the system can be very unpredictable about when it will activate your extension to run your reload logic. My suggestion is to generate timeline entries well past the time when you want to refresh with your best guess as to what it should look like then, and let those get replaced whenever your timeline does get refreshed.
Oct ’20
Reply to iOS 14 widget - clock with sweeping seconds
It is not possible for 3rd party widgets to animate on the scale of seconds. The only way your widget can change that fast is if you use the provided relative time text strings which can tick seconds. Attempting to create timeline entries for every second will not work correctly. In my testing it doesn't end up refreshing any faster than every 5 seconds in the best case scenario.. Hour/minute dials are certainly possible since 1 timeline entry every minute is well within reason, just don't try to create an entire day's worth of entries at one time. Pro tip: If you are trying to update on the minute, make sure you zero out the seconds for your timeline entires since it is really easy to end up using whatever seconds value gets returned by Date()
Oct ’20