protocol TodoUseCase {
func add(title: String, description: String) -> Completable
}
final class CreateTodoPresenterImpl: CreateTodoPresenter {
var todoUseCase: TodoUseCase!
var bag = DisposeBag()
func setBind() {
requestCreateTodoRelay
.flatMap { [weak self] _ -> Completable in
guard let weakSelf = self else { return Completable.empty() }
return weakSelf.todoUseCase.add(title: weakSelf.titleInputtedText.value, description: weakSelf.descriptionInputtedText.value)
.debug() // debug#1
}
.debug() // debug#2
.subscribe(onError: { [weak self] error in
self?._showAPIErrorPopupRelay.accept(error)
}, onCompleted: { [weak self] in
self?.toLoginView()
})
.disposed(by: bag)
}
}
Why this function todoUseCase.add() -> Completable, but does return nothing.
I want that when this todoUseCase.add called, call subscribe's onCompleted closure.
I tried to investigate this
debug#1 return onCompleted
debug#2 return nothing
I have a question, calling the returning Completable method inside of the flatMap method is wrong?
A
flatMapdoes not complete until all subscribed Observables complete. In this case, that means thatrequestCreateTodoRelayand every Observable created by the closure would all have to complete before the flatMap emitted a completed event.It makes sense when you consider that once the Observable returned from flatMap emits a complete, it's not allowed to emit any other events. So it wouldn't be able to react properly when
requestCreateTodoRelayemitted another next event.The solution is to have
.add(title:description:)return aSingle<Void>(or anObservable<Void>that emits both a next event and a completed event.This is a general rule by the way. If an observable is responding to multiple upstream observables, it will emit an error if any one upstream observable emits and error, but won't emit a completed event unless all upstream observables do so.