As of RxSwift4, Variable
is moved to Deprecated.swift
marking the possible deprecation of Variable
in future. An alternate proposed to Variable
is BehaviorRelay
. While posting this question, as I could not find much of the tutorial on web using BehaviorRelay
am posting such a fundamental question here in SO.
Assume I have a webService call going on and I receive a chunk of data which is JSONArray, on parsing JSON object one by one I update my Variable's value property
Here is my variable declaration
var myFilter = Variable<[MyFilterModel]>([MyFilterModel(data: "{:}")])
on getting a new element each time I would update my Variable as
myFilter.value.append(newModel)
As Variable was bind to CollectionView, collectionVie would update its UI immediately with the newly added object.
Issue with BehaviorRelay
Now my declaration looks like
var myFilter = BehaviorRelay<[MyFilterModel]>(value: [MyFilterModel(data: "{:}")])
But biggest issue is myFilter.value
is readOnly. So obviously
myFilter.value.append(newModel)
is not a solution. I figured out that I can use accept
rather.
But now when I try to parse each element in response and update the value of myFilter
self?.expertsFilter.accept(newModel)
The above statement gives error quoting
Can not convert the value of NewModel to expected arguement type [NewModel]
Obviously, its expecting a array and not a individual element.
Workaround:
Solution 1:
So one solution is accumulate all the response in a temporary array and once done trigger self?.expertsFilter.accept(temporary_array)
Solution 2:
If I have to send onNext
event to subscriber on parsing each element, I need to copy the value of self?.expertsFilter to new Array, add the newly parsed element to it and return the new array.
Solution 3:
Get rid of BehaviorRelay
and use BehaviorSubject
/PublishSubject
First two sounds depressing, because there may be a need to trigger UI on parsing each element I cant wait till entire response is parsed. So obviously solution1 is not much of use.
Second solution is much more horrible because it creates a new array (I know its temporary and will be released) every time to send onNext event.
Question:
Because BehaviorRelay
is proposed as a alternate to Variable
am in dilemma, am using accept
correctly?? Is there a better way to solve it?
Please help
Building on Dalton's answer, here is a handy extension:
I created those this extension, with two methods to facilitate migration in case you have a Variable of Array and you have to use append.
and you call it like this
Have you considered simply creating a new array from the existing value on the relay, appending, then calling
accept
?I wrote this extension for replacing
Variable
s withBehaviorRelay
s. You can add whatever method you need based on this pattern to migrate easily.Instead of
Variable.value.funcName
, now you writeBehaviorRelay.funcName
.The idea to use
where Element: RangeReplaceableCollection
clause comes from retendo's answerAlso note that the
index
is of typeElement.Index
, notInt
or whatever else.I would do something like that -
AshKan answer is great but I came here looking for a missing method from the solution. Append: