Rxswift: Use Zip with Different Type Observables

RxSwift: Use Zip with different type observables

This works for me. I tested it in Xcode7, RxSwift-2.0.0-beta

zip(just(1), just("!")) { (a, b) in 
return (a,b)
}

Using zip operator in RxSwift after creating an array of observables

How about something like this?

let saves = saveTaps.withLatestFrom(newBid)
.flatMapLatest { (bid: Bid) -> Observable<[Bool]> in
let dataSaved = CustomerManager.shared.bidCreate(bid: bid)
.catchErrorJustReturn(false)

let photosSaved = bid.images.map {
CustomerManager.shared.bidUploadFile(image: $0, bidID: bid.id)
.catchErrorJustReturn(false)
}

return Observable.zip([dataSaved] + photosSaved)
.trackActivity(activityIndicator)
}
.asDriver(onErrorJustReturn: []) // remove this line if you want an Observable<[Bool]>.

RxSwift: Combining different types of observables and mapping result

Your comment describes a different use-case than what the question describes...

updatedValue is changed with every key strike, isChanged is called only when update button is tapped while savedValue is orignal value.

The above implies that you want something like:

func example<Value>(savedValue: Value, isChanged: Observable<Void>, updatedValue: Observable<Value>) -> Observable<Value> {
isChanged
.withLatestFrom(updatedValue)
.startWith(savedValue)
}

The above will emit the savedValue, then emit whatever was last emitted by updatedValue every time isChanged emits. I suggest you change the name of isChanged to something else since it isn't a Bool.

Meanwhile, the question implies that you want something more like:

func exampleʹ<Value>(savedValue: Value, isChanged: Observable<Bool>, updatedValue: Observable<Value>) -> Observable<Value> {
isChanged
.withLatestFrom(updatedValue) { $0 ? savedValue : $1 }
}

The above will also emit a value every time isChanged emits a value. It will emit savedValue whenever isChanged emits false and updatedValue whenever isChanged emits true.


If savedValue is an Observable (maybe from a network request or a DB get) then the code would look more like this:

func example<Value>(isChanged: Observable<Void>, savedValue: Observable<Value>, updatedValue: Observable<Value>) -> Observable<Value> {
savedValue
.concat(
isChanged.withLatestFrom(updatedValue)
)
}

func exampleʹ<Value>(isChanged: Observable<Bool>, savedValue: Observable<Value>, updatedValue: Observable<Value>) -> Observable<Value> {
isChanged
.withLatestFrom(Observable.combineLatest(savedValue, updatedValue)) { $0 ? $1.0 : $1.1 }
}

RxSwift: Subscribe to Observable.zip. Handle result as tuple?

Just change map to flatMap, result will change to tuple instead Observable.

IoC.networkProcessService.getInfoA(with: identifier)
.flatMap { infoA -> Observable<(InfoB, InfoC)> in

return Observable.zip(
IoC.networkProcessService.getInfoB(with: infoA),
IoC.networkProcessService.getInfoC(with: infoA)
{ return ($0, $1) }

}
.subscribe(onNext: { result in
print(result)

// result is of type (InfoB, InfoC)

}, onError: { error in
Logger.main.log(category: [.network, .error], arguments: error.localizedDescription)

})
.disposed(by: disposeBag)

How to pass RxSwift zip with calling function response of other 2 function

Based on the question asked, here's what you are looking for:

func example<T, U, V>(first: () -> Observable<T>, second: () -> Observable<U>, third: @escaping (T, U) -> Observable<V>) -> Observable<V> {

return Observable.zip(first(), second())
.flatMap(third)
}

RXSwift Zip operator N items via an enumerable

It can handle more than 8 if you use it on CollectionType.

Here's the method definition:

extension CollectionType where Generator.Element : ObservableType {
public func zip<R>(resultSelector: [Generator.Element.E] throws -> R) -> Observable<R> {
return ZipCollectionType(sources: self, resultSelector: resultSelector)
}
}

So instead of using it like this:

Observable.zip(o1, o2, o3, o4, o5, o6, o7, o8, o9) { ... }

Use it like this:

[o1, o2, o3, o4, o5, o6, o7, o8, o9].zip { ... }

Understanding difference between zip and combineLatest with RxSwift for sequence parameters

combineLatest is a bit easier to understand (and more useful!) if the two observables don't emit elements immediately. An easier-to-understand example (which I encourage you to try) is:

Observable.combineLatest(someUISwitch.rx.isOn, someUITextField.rx.text) { isOn, text in
return "Text: \(text ?? ""), Switch is on: \(isOn)"
}.subscribe(onNext: { value in
print(value)
}).disposed(by: disposeBag)

Try adding a UISwitch and a UITextField into your UI. Now try entering some text into the text field, and also try switching the switch. You will see that whenever one of the two changes, that is, when either observable emits a new value, their combined value (combined by the closure passed to combineLatest) gets emitted by the combined observable.

More generally, the observable produced by combineLatest emits its first value when all the observables first emits a value, and subsequent values are emitted when any of the observables emits a value. Whenever it emits a value, the value it emits is computed by combining all the latest values that all the observables have emitted. Hence "combine latest".

For your Observable.of example, the values are all emitted immediately, but combineLatest behaves as if left and right emits values in an interlaced order, and left goes first. I've tried to add annotations to the output you got. See if this helps your understanding.

    (left emits sunny)
(right emits Lisbon)
It's sunny in Lisbon (the first values emitted by both observables)
(left emits cloudy)
It's cloudy in Lisbon
(right emits Copenhagen)
It's cloudy in Copenhagen
(left emits 2nd cloudy)
It's cloudy in Copenhagen
(right emits London)
It's cloudy in London
(left emits sunny)
It's sunny in London
(right emits Madrid)
It's sunny in Madrid
(right emits Vienna, since left ran out)
It's sunny in Vienna

Also, don't forget there's RxMarbles that you can play with.



Related Topics



Leave a reply



Submit