Reputation: 6971
I'm really really new to Rx and RxSwift and I'm trying to learn by reading and doing at the same time, so maybe this question makes you laugh. Please, excuse me in advance :P
I have this architecture:
MatchView -> MatchViewModel -> P2PSession -> MCSession+Rx
I've made a Reactive extension of MCSession
to make session state changes an observable:
var didChangeState: Observable<(MCPeerID, MCSessionState)> {
return RxMCSessionDelegateProxy.proxy(for: base).didChangeStateSubject.asObservable()
}
Then, I have another object, P2PSession
, subscribed to that observable in order to transform the received event to emit it to a BehaviorSubject<MCPeerID?>
to be observed by my MatchViewModel
, that will transform it to emit to a Variable<String>
to be shown in a label.
Maybe that chaining is totally ridiculous but here is the complete (but simplified) thing:
P2PSession
var connectedPeer: BehaviorSubject<MCPeerID?> = BehaviorSubject(value: nil)
mcSession.rx.didChangeState
.subscribe(onNext: { self.connectedPeer.onNext($0.0) })
.disposed(by: disposeBag)
MatchViewModel
var peerName = Variable("")
p2pSession.connectedPeer.asObservable()
.map({ $0?.displayName ?? "None" })
.subscribe(onNext: { self.peerName.value = $0 })
.disposed(by: disposeBag)
MatchView
viewModel.peerName.asDriver()
.drive(peerLabel.rx.text)
.disposed(by: disposeBag)
It works, as a peer connects, a delegate method is called in the RxMCSessionDelegateProxy
and data travels through the chain until it is shown in the label.
But I think that could be made way more elegant. Is it possible to forward a transformed event from an observable to a subject without making the subscription to the first observable to transform and inject the value to the subject/variable? (as I make in P2PSession
). I don't know if I've explained myself correctly but I think that's possible with flatMap
but I'm not getting it correctly, maybe I need the subscribe
anyway and I'm trying to do stupid things.
Thank you so much, I need your help!
Upvotes: 1
Views: 1066
Reputation: 4735
Expose the connected peer via an Observable
, and the peer name through a Driver
:
let connectedPeer: Observable<MCPeerID?>
connectedPeer = mcSession.rx.didChangeState.map { $0.0 }
let peerName: Driver<String>
peerName = p2pSession.connectedPeer.map { $0.displayName ?? "None" }.asDriver(onErrorJustReturn: "None")
viewModel.peerName.drive(peerLabel.rx.text).disposed(by: disposeBag)
Upvotes: 2