I have a simple signal, in one of the app components, that returns an array of items:
var itemsSignal: Signal<[Item], Never>
Those items might contain updates for the data that are rendered on the screen in a form of a table view. The task is to apply the updates to the cells if they are present on the screen.
There are two possible ways, that I can think of, on how this can be done. The app is written in MVVM style, but I will simply for the purposes of example.
The first way is to subscribe to this signal once on a level of view controller code, then in an observeValues
block check wherever we receive the updates for the items on screen with some for-loop and update the states for the corresponding cells. This way we will have only a single subscription, but this introduce unnecessary, in my mind, code coupling, when we basically use view controller level code to pass updates from the source to individual cells on screen.
The second way is to subscribe to this signal from each individual cell (in reality cell's view model) and apply some filtering like this:
disposables += COMPONENT.itemsSignal
.flatten()
.filter({ $0.itemId == itemId })
.observeValues({
...
})
But this creates multiple subscriptions - one for each individual cell.
I actually prefer the second method, as it much cleaner from a design stand point, in my mind, as it doesn't leak any unnecessary knowledge to view controller level code. And wherever the same cell is re-used on a different screen this self-updating behaviour will be inherited and will work out of the box.
The question is how much more memory/cpu expensive is the second method due to multiple subscriptions? In this project we use ReactiveSwift
, but I think this is relevant for other Rx
libraries as well.