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.
-
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
MyProvider
conforms toTimelineProvider
protocol:I assume
MyProvider
should be made a part of AppEnvironment. If I understand correctly, instead of loading data inside the callbackgetTimeline
it is better to do this inappReducer
by 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
appReducer
andMyProvider
at the moment. Moreover,TimelineProvider
protocol 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