How to use BehaviorRelay as an alternate to Variable in RxSwift?
Solution 1:
Have you considered simply creating a new array from the existing value on the relay, appending, then calling accept
?
myFilter.accept(myFilter.value + [newModel])
Solution 2:
Building on Dalton's answer, here is a handy extension:
extension BehaviorRelay where Element: RangeReplaceableCollection {
func acceptAppending(_ element: Element.Element) {
accept(value + [element])
}
}
Solution 3:
I wrote this extension for replacing Variable
s with BehaviorRelay
s. You can add whatever method you need based on this pattern to migrate easily.
public extension BehaviorRelay where Element: RangeReplaceableCollection {
public func insert(_ subElement: Element.Element, at index: Element.Index) {
var newValue = value
newValue.insert(subElement, at: index)
accept(newValue)
}
public func insert(contentsOf newSubelements: Element, at index: Element.Index) {
var newValue = value
newValue.insert(contentsOf: newSubelements, at: index)
accept(newValue)
}
public func remove(at index: Element.Index) {
var newValue = value
newValue.remove(at: index)
accept(newValue)
}
}
Instead of Variable.value.funcName
, now you write BehaviorRelay.funcName
.
The idea to use where Element: RangeReplaceableCollection
clause comes from retendo's answer
Also note that the index
is of type Element.Index
, not Int
or whatever else.
Solution 4:
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.
extension BehaviorRelay where Element: RangeReplaceableCollection {
func append(_ subElement: Element.Element) {
var newValue = value
newValue.append(subElement)
accept(newValue)
}
func append(contentsOf: [Element.Element]) {
var newValue = value
newValue.append(contentsOf: contentsOf)
accept(newValue)
}
public func remove(at index: Element.Index) {
var newValue = value
newValue.remove(at: index)
accept(newValue)
}
public func removeAll() {
var newValue = value
newValue.removeAll()
accept(newValue)
}
}
and you call it like this
var things = BehaviorRelay<[String]>(value: [])
things.append("aa")
let otherThings = ["bb", "cc"]
things.append(contentsOf: otherThings)
things.remove(at: 0)
things.removeAll()
Solution 5:
I would do something like that -
let requests = PublishSubject<Observable<ServerResponse>>.create()
let responses: Observable<ServerResponse> = requests.switchLatest()
let parsed: Observable<[ParsedItem]> = responses
.flatMap { Observable.from($0).map { parse($0) }.toArray() }
parsed.bind(to: ui)
// repeated part
let request1: Observable<ServerResponse> = servive.call()
request.onNext(request1)