Replies: 1 comment 4 replies
-
I just learn TCA, and ViewStore is one of my concerns. ViewStore keeps a copy (!) of the Store.state, and also subscribes to it, so any change in Store.state is immediately propagated to ViewStore.state. This subscription is done on thread (dispatch queue) where the ViewStore initializer is called. Also, ViewStore sends actions to Store. So, my understanding is, that you can run all the ViewStore on any queue (thread), but it must be the thread where you have created the ViewStore, AND, it must be the queue (thread) where the Store is operated. This seems to be easy, but do not forget on environment used in the Store, that now will be called from non-main thread. Also effects should publish actions on the correct queue. Please, correct me, if I am wrong, it helps me in my understanding TCA... :) |
Beta Was this translation helpful? Give feedback.
-
I really love how State, Actions, and Reducers allow you to model things in an exhaustive manner. The way I see it TCA seems to be very focused on producing output for SwiftUI to consume through Observable Object and so forth. But I think it would work quite well for modeling things as a non-view based service as well. What if I'd like to model business logic that operates on state and delivers it's output without the assumption of a view to consume it (a headless/viewless ViewStore for example). The way I see it is my inputs are the Store send actions, the output is the Store publisher, and if everything else remains the same (State, Action, Env, Reducer) I'd essentially have something like a micro service. Is there any reason why I couldn't use a ViewStore on a "non-View" thread so long as it's on a single synchronous thread?
I've created somewhat of a prototype that seems to work well. Essentially I have an iOS app that uses TCA normally, but then I've wrapped parts of an in-house SDK in a separate TCA ViewStore (without a View), which for disambiguation I'll call a ServiceStore. Then I inject the ServiceStores publisher as an AnyPublisher in the Application's RootEnvironment where it eventually get's subscribed to by one of the Application's scoped down Stores. I also injected the ServiceStore's send actions as closures in the Env. Being that they both operate on the Main queue I find that sometimes sending an action to the ServiceStore from an Application ViewStore triggers the assertion within the send method (file: Store.swift > send(_:)) unless I wrap the call to send in a .fireAndForget.
The ServiceStore and the ViewStore are completely separate and communicate through the ViewStore's env. I think this assertion is triggered because they are both operating on the same thread (main queue) and that the send to the ServiceStore triggers work that sometime happens without any delay that gets delivered back to the ViewStore. The fireAndForget reliably resolves this. Also there are aspects of the in-house SDK that I'm trying to wrap where the operations are expected to be on a non-main queue, which brings me to the following inquiries.
I really enjoy using TCA and would like to model a service in it that can be consumed by an iOS app. Are there any reasons why I should or should not do this? Also is there any documentation for setting up and operating a ViewStore on a synchronous, but non-main queue? Please feel free to let me know if I'm way out in left field and shouldn't be doing things this way.
Beta Was this translation helpful? Give feedback.
All reactions