RxSwift正确地关闭处理预订

时间:2018-07-28 03:40:28

标签: ios swift rx-swift

我正在围绕Firebase身份验证功能编写包装器,以返回Observable并添加其他profileIncomplete状态。它基本上首先检查用户是否已登录,如果已登录,则检查用户的个人资料是否完整。以下是我的代码,我想知道是否可以在Observable.create中订阅一个可观察对象,如果可以,在这种情况下如何正确处置一次性对象?在闭包内部创建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> { ... }

2 个答案:

答案 0 :(得分:2)

我认为在Observable.create(或其他订阅块)中进行订阅是一种代码嗅觉。

似乎您有两个不同的问题。 stateChangedprofileCompleted

我会将它们分为两种不同的方法,listenToAuthState仅负责反映addStateDidChangeListener的结果,而listenToProfileCompleted有一个单独的方法。

这将使您拥有一个单独的“就绪”(或者您想称呼它),可以将两者压缩。或者,如果在侦听配置文件完成之前必须更改身份验证状态,请使用flatMap。

答案 1 :(得分:0)

要处置资源,可以将其添加到DisposeBag。像下面一样

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
        }
    }
}