Skip to content

Instantly share code, notes, and snippets.

@shaundon
Last active February 26, 2023 02:53
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shaundon/b4b823fbcac863d24c1ebe751cc97cfc to your computer and use it in GitHub Desktop.
Save shaundon/b4b823fbcac863d24c1ebe751cc97cfc to your computer and use it in GitHub Desktop.
Proof of concept of using caches in WidgetKit.
/**
Most of this file has been omitted to only focus on the caching aspect, but in reality
it would be a standard widget template.
**/
struct MyWidgetProvider: IntentTimelineProvider {
// Initialise the cache.
private let cache = MyWidgetCache()
func getEntries(for configuration: ConfigurationIntent, in context: Context, completion: @escaping ([MyWidgetEntry]?) -> ()) {
getWorkouts { error, workouts in
// If something goes wrong, try to use a cached entry.
if let error = error {
guard let cachedEntry = cache.newEntryFromPrevious(withDate: Date(), forConfiguration: configuration) else {
completion(nil)
return
}
completion([cachedEntry])
return
}
// If no errors, make an entry, cache it, and return it.
let entry = MyWidgetEntry(date: Date(), configuration: configuration, workoutsCount: workouts.count)
cache.storePreviousEntry(entry, withConfiguration: configuration)
completion([entry])
}
}
}
class MyWidgetCache: WidgetCache {
typealias TimelineEntryType = MyWidgetEntry
typealias ConfigurationIntentType = MyWidgetConfigurationIntent
var previousEntries = [MyWidgetConfigurationIntent: MyWidgetEntry]()
func newEntryFromPrevious(withDate date: Date, forConfiguration configuration: MyWidgetConfigurationIntent) -> MyWidgetEntry? {
if previousEntries.isEmpty { return nil }
guard let indexOfPreviousEntry = previousEntries.index(forKey: configuration) else { return nil }
let previousEntry = previousEntries[indexOfPreviousEntry].value
return MyWidgetEntry(
date: date,
configuration: previousEntry.configuration,
workoutsCount: previousEntry.workoutsCount
)
}
func storeNewEntry(_ entry: MyWidgetEntry, withConfiguration configuration: MyWidgetConfigurationIntent) {
previousEntries[configuration] = entry
}
}
protocol WidgetCache {
associatedtype TimelineEntryType: TimelineEntry
associatedtype ConfigurationIntentType: INIntent
var previousEntries: [ConfigurationIntentType: TimelineEntryType] { get set }
func newEntryFromPrevious(withDate date: Date, forConfiguration configuration: ConfigurationIntentType) -> TimelineEntryType?
func storeNewEntry(_ entry: TimelineEntryType, withConfiguration configuration: ConfigurationIntentType) -> Void
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment