RxSwiftCommunity / RxRealm

RxSwift extension for RealmSwift's types
MIT License
1.15k stars 263 forks source link

Observable.from(optional: ...) completing after emitting initial value #131

Closed mckapur closed 4 years ago

mckapur commented 4 years ago

Sorry for the previous issue without much info — here's a new ticket.

When creating an Observable from a managed Realm object using Observable.from(optional: managedRealmObj), the expected behavior is that — similar to using Observable.from(object: managedRealmObj) — a stream should be created that emits an initial value of the object, and then new values when the update is updated via a write to the Realm. If the value passed in is nil, it should emit nil and then complete and dispose.

However, this is not the case. Instead, the stream is created with a non-nil item, an item is emitted (the initial value), and then the stream immediately completes and is then disposed.

Here are some logs to demonstrate this:

2019-08-13 01:37:09.318: [Observable.from(optional: ...) is broken!] -> subscribed
2019-08-13 01:37:09.319: [Observable.from(optional: ...) is broken!] -> Event next(User {
2019-08-13 01:37:09.320: [Observable.from(optional: ...) is broken!] -> Event completed
2019-08-13 01:37:09.320: [Observable.from(optional: ...) is broken!] -> isDisposed

Observable.from(optional: ...) is useful because I can have Observables with optional values, eg. say a logged in user that should be nil if there is no such user, and would return an Observable user from Realm if it was not nil. The other alternative right now would be to emit errors instead, but this is not ideal.

alekop commented 4 years ago

I just ran into the same issue. Is this resolved? Strange that there is no activity on this issue.

M0rtyMerr commented 4 years ago

Hey @mckapur @alekop thank you for raising this question! Observable.from(optional:) is RxSwift method, not RxRealm. It knows nothing about Realm.Object specific semantic (such as observing changes). The main purpose of this method (from RxSwift docs):

Converts a optional to an observable sequence

It simply checks if optional is empty, emits its value and then completes.

So, this is required behaviour and it can't be "fixed". If you want to have Observable<User?> you can try something like this:

let loggedIn = BehaviorSubject<Bool>(value: false)
let user = Observable.from(object: user)
let loggedUser: Observable<User?> = Observable.combineLatest(loggedIn, user) { logged, user in
  logged ? user : nil    
}
M0rtyMerr commented 4 years ago

Closing this due to lack of activity