Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use BehaviorRelay as an alternate to Variable in RxSwift?

Tags:

rx-swift

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

like image 992
Sandeep Bhandari Avatar asked Nov 23 '17 09:11

Sandeep Bhandari


People also ask

What is behavior relay in RxSwift?

RxSwift also provides a concept called Relays. RxSwift provides two of these, named PublishRelay and BehaviorRelay . These wrap their respective subjects, but only accept and relay next events. You cannot add a completed or error event onto relays at all, so they're great for non-terminating sequences.

Is BehaviorRelay thread safe?

The method is thread-safe.

What is PublishSubject RxSwift?

RxSwift: Publish SubjectUseful when you want subscribers to be notified of new events from the point at which they subscribed until they either unsubscribe or termination ( . completed / . error ). Will emit stop event to new subscribers and no longer emit .

What is variable RxSwift?

Variable is a concept added into RxSwift in its early days which basically let you create an imperative bridge by “setting” and “getting” a current value to and from it. It was a seemingly helpful measure to get developers started with RxSwift until they fully understand “Reactive Thinking”.


Video Answer


2 Answers

Have you considered simply creating a new array from the existing value on the relay, appending, then calling accept?

myFilter.accept(myFilter.value + [newModel]) 
like image 90
dalton_c Avatar answered Sep 21 '22 19:09

dalton_c


Building on Dalton's answer, here is a handy extension:

extension BehaviorRelay where Element: RangeReplaceableCollection {     func acceptAppending(_ element: Element.Element) {         accept(value + [element])     } } 
like image 31
retendo Avatar answered Sep 18 '22 19:09

retendo