I am writing a wrapper around Firebase authentication functions to return Observable
and add additional profileIncomplete
state. It basically first checks whether a user is logged in, if so, check whether the user's profile is complete. The following is my code, I wonder whether it is okay to subscribe to an observable in Observable.create
and, if so, how do I properly dispose the disposable in this case? create a DisposeBag
inside the closure?
enum State {
case loggedIn
case profileIncomplete
case notLoggedIn
}
func listenToAuthState() -> Observable<State> {
return Observable.create { observable in
let authStateHandle = Auth.auth().addStateDidChangeListener() { [weak self] (_, user) in
guard let user = user else {
observable.onNext(.notLoggedIn)
return
}
let disposable = self?.listenToProfileCompleted(uid: user.uid).subscribe(onNext: { (completed) in
if completed {
observable.onNext(.loggedIn)
observable.onCompleted()
} else {
observable.onNext(.profileIncomplete)
}
})
// How to dispose the disposable???
}
return Disposables.create {
Auth.auth().removeStateDidChangeListener(authStateHandle) }
}
}
func listenToProfileCompleted(uid: String) -> Observable<Bool> { ... }
I think subscribing inside a Observable.create
(or inside a different subscribe block) is a code-smell.
It seems you have two separate concerns. stateChanged
and profileCompleted
.
I would split those into two different methods, having listenToAuthState
only in charge of reflecting the result of addStateDidChangeListener
, and have a separate one for listenToProfileCompleted
.
This will let you have a separate "ready" (or however you want to call it) that can zip the two. Or otherwise use flatMap, if the auth status must change before you listen to the profile completion.
To dispose resource you can add it to DisposeBag. Like below
func listenToAuthState() -> Observable<State> {
return Observable.create { observable in
var disposeBag:DisposeBag! = DisposeBag()
let authStateHandle = Auth.auth().addStateDidChangeListener() { [weak self] (_, user) in
guard let user = user else {
observable.onNext(.notLoggedIn)
return
}
let disposable = self?.listenToProfileCompleted(uid: user.uid).subscribe(onNext: { (completed) in
if completed {
observable.onNext(.loggedIn)
observable.onCompleted()
} else {
observable.onNext(.profileIncomplete)
}
}).disposed(by: disposeBag)
// How to dispose the disposable???
}
return Disposables.create {
Auth.auth().removeStateDidChangeListener(authStateHandle)
disposeBag = nil
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.