[英]RxSwift properly dispose subscription in closure
I am writing a wrapper around Firebase authentication functions to return Observable
and add additional profileIncomplete
state. 我正在围绕Firebase身份验证功能编写包装器,以返回
Observable
并添加其他profileIncomplete
状态。 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? 以下是我的代码,我想知道是否可以在
Observable.create
订阅一个observable,如果可以的话,在这种情况下如何正确处置该一次性对象? create a DisposeBag
inside the closure? 在封闭内部创建一个
DisposeBag
?
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. 我认为在
Observable.create
内部(或在其他订阅块中)进行订阅是一种代码嗅觉。
It seems you have two separate concerns. 看来您有两个不同的问题。
stateChanged
and profileCompleted
. stateChanged
和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
. 我将它们分为两种不同的方法,让
listenToAuthState
仅负责反映addStateDidChangeListener
的结果,并为listenToProfileCompleted
提供单独的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.
否则,如果在侦听配置文件完成之前必须更改身份验证状态,请使用flatMap。
To dispose resource you can add it to DisposeBag. 要处置资源,可以将其添加到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
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.