WidgetKit extensions #1170
Replies: 1 comment 1 reply
-
|
Hi @filip-zielinski-intive, this is an interesting question, and we don't currently have much info on it. We should probably add a case study soon. First, we do not think it's appropriate to add Second, you can pass the view store to struct MyWidget: Widget {
let kind: String = "MyWidget"
let store = Store(...)
var body: some WidgetConfiguration {
StaticConfiguration(
kind: kind,
provider: MyProvider(viewStore: ViewStore(self.store))
) {
...
}
}
}
struct MyProvider: TimelineProvider {
let viewStore: ViewStore<AppState, AppAction>
...
}Note that the view store is held as a Next, you can send actions to the view store whenever one of the provider's endpoints is called, and then read the state. This works because So, for example, in the func placeholder(in context: Context) -> MyTimelineEntry {
viewStore.send(.timelineProviderRequestsPlaceholder)
return viewStore.timelinePlaceholder
}This works nicely because you don't need to perform any effects in order to construct the placeholder. The func getSnapshot(
in context: Context,
completion: @escaping (MyTimelineEntry) -> Void
) {
viewStore.send(.timelineProviderRequestsSnapshot)
// wait for effect to finish and invoke completion
// with data from the view store???
}Soon we will actually have a really nice way to accomplish this using some new concurrency tools we are adding to the library that allow you to func getSnapshot(
in context: Context,
completion: @escaping (MyTimelineEntry) -> Void
) {
Task {
await viewStore.send(.timelineProviderRequestsSnapshot).finish()
completion(viewStore.timelineSnapshot)
}
}Until then you can still accomplish this, but just in a slightly less ergonomic way. There's a method called func getSnapshot(
in context: Context,
completion: @escaping (MyTimelineEntry) -> Void
) {
Task {
await viewStore.send(.timelineProviderRequestsSnapshot, while: \.isLoading)
completion(viewStore.timelineSnapshot)
}
}You must make sure to set Or you can hold onto func getSnapshot(
in context: Context,
completion: @escaping (MyTimelineEntry) -> Void
) {
Task {
await viewStore.send(.timelineProviderRequestsSnapshot, while: { $0.timelineSnapshot == nil })
completion(viewStore.timelineSnapshot)
viewStore.send(.timelineSnapshotFinished)
}
}That's the rough idea at least. Good luck! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm implementing WidgetKit extension and trying to apply the architecture for it, but don't see how to do this properly. Widget is described the following way:
where
MyProviderconforms toTimelineProviderprotocol:I assume
MyProvidershould be made a part of AppEnvironment. If I understand correctly, instead of loading data inside the callbackgetTimelineit is better to do this inappReducerby running an effect. The problem is I don't see how to be notifiedthat data loading should be performed, cause there are no connections between
appReducerandMyProviderat the moment. Moreover,TimelineProviderprotocol requires the relevant completion to be invoked, wouldn't it be a problem to do this in a reducer when data is loaded?Generally speaking, I don't understand how to build an infrastructure for this use case. Any ideas? Thanks in advance.
Beta Was this translation helpful? Give feedback.
All reactions