Reputation: 4564
I'm a newbie to RxSwift and I'm trying to implement login facebook feature, and here's what I'm doing:
loginButton.rx.tap
.debug("login tapped")
.flatMap { [weak self] ()->Observable<AccessToken> in
guard let strongSelf = self else {
throw NetworkError.requestCancelled
}
return strongSelf.viewModel.loginFacebook(from: strongSelf)
}
.flatMap { [weak self] accessToken->Observable<(accessToken: String, userId: String)> in
guard let strongSelf = self else {
throw NetworkError.requestCancelled
}
return strongSelf.viewModel.requestUserInfo(token: accessToken)
}
.flatMap { [weak self] (accessToken: String, userId: String)->Observable<LoginResult> in
guard let strongSelf = self else {
throw NetworkError.requestCancelled
}
return strongSelf.viewModel.authenticate(accessToken: accessToken, userId: userId)
}
.catchError({ error -> Observable<LoginResult> in
return Observable.just(LoginResult.failure(error: error as! NetworkError))
})
.subscribe (onNext:{ [weak self] result in
guard let strongSelf = self else {
return
}
switch result {
case .success:
// do something with success
}
case .failure(let error):
// do something with error
}
}, onCompleted: {
print("rx.tap completed")
})
.disposed(by: disposeBag)
The thing is when I tap login button then close the login window of Facebook that pops up, my subscription to rx.tap
reaches onCompleted
, so then when I try to tap the button again, nothing happens. How should I handle this case? Any suggestion would help.
Upvotes: 2
Views: 1721
Reputation: 5679
That is a simplified scheme of your chain:
loginButton.rx.tap
.flatMap({ (_) -> Observable<Void> in
throw NSError(domain: "", code: 0, userInfo: [:])
})
.catchError({ error -> Observable<Void> in
return Observable<Void>.just()
})
.subscribe()
When you produce Observable<Void>.just()
in catchError
block or something similar in other blocks, it will fire only once and that is why you receive completed
and nothing else happens later. I advice to put all the code you have into flatMapLatest
for example. The result code will be:
loginButton.rx.tap
.flatMapLatest({ _ -> Observable<Void> in
return Observable<Void>
.just()
.flatMap({ (_) -> Observable<Void> in
throw NSError(domain: "", code: 0, userInfo: [:])
})
.catchError({ error -> Observable<Void> in
return Observable<Void>.just()
})
})
.subscribe()
Hope it helps
P.S. Check the similar answer from the RxSwift development team member
Upvotes: 2