ReactiveX / RxSwift

Reactive Programming in Swift

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ConnectableObservable cannot connect once it was disposed

tomcheung opened this issue · comments

Short description of the issue:
When a ConnectableObservable call .connect() and dispose it, call .connect() again will not able to start the subscription

Expected outcome:

Not sure it is intended behaviour, but i expect it can be start the subscription again on when .connect() is called again

What actually happens:

No event received

Self contained code example that reproduces the issue:

let timer = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
    .replay(1)

timer.subscribe { i in
    print("Time:", i)
}

let firstSubscription = timer.connect()

DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
    firstSubscription.dispose()
}

DispatchQueue.main.asyncAfter(deadline: .now() + 8) {
    let secondSubscription = timer.connect()
}

RxSwift/RxCocoa/RxBlocking/RxTest version/commit

6.6.0

Platform/Environment

  • iOS
  • macOS
  • tvOS
  • watchOS
  • playgrounds

How easy is to reproduce? (chances of successful reproduce after running the self contained code)

  • easy, 100% repro
  • sometimes, 10%-100%
  • hard, 2% - 10%
  • extremely hard, %0 - 2%

Xcode version:

  15.2

⚠️ Fields below are optional for general issues or in case those questions aren't related to your issue, but filling them out will increase the chances of getting your issue resolved. ⚠️

Installation method:

  • SPM

This is as designed, but it will take a bit of explaining. The TL:DR is that you should use .multicast(ReplaySubject<Int>.create(bufferSize: 1)) for this use-case.

The replay(1) operator is a wrapper around the .multicast { ReplaySubject.create(bufferSize: 1) } operator. This operator creates a Subject using the closure and when it's subscribed to, it binds the subscriber(s) to the subject. When connect is called, it binds the subject to the source and all the subscribers start receiving events.

When the connection is disposed, it destroys the Subject and therefore looses all the subscriptions. In essence, it only replays events to subscribers that subscribe while the source is emitting.

If you want to hold on to the values for longer, you need to use the multicast(_:) that takes a Subject object rather than a closure that creates a Subject. When you do that, all connections will use the same Subject object which will exist as long as the connectable exists.

I see, thanks for detail explaination, i think it is clear enough and can close this issue