I have a combine construct to combine calls to the functions that return AnyPublishers. [credVendor.credentials() and credVendor.accessToken()]. The issue here is that the call to the publisher does not return back sometimes and the application freezes and the scheduler for timeout does not work.
But when I use a DispatchQueue.main instead of DispatchQueue.global() on the scheduler this behavior never happens. I would like to understand this weird behavior. I pretty new to iOS and still learning. I would really appreciate if someone can point me in the right direction.
Code for the combine.
anyCancellable = credVendor.credentials()
.combineLatest(credVendor.accessToken())
.eraseToAnyPublisher()
.catch { error -> AnyPublisher<(Credentials, AccessToken), Error> in
return Fail(outputType: (Credentials, AccessToken).self, failure: error).eraseToAnyPublisher()
}
.sink(
receiveCompletion: { completion in
switch completion {
case .failure:
let error = Error(message: "\(self) Could not find credentials.", type: .credentialsError)
completionHandler?(false, error)
default: ()
}
},
receiveValue: { [weak self] credentials, accessToken in
guard let self = self else {
return
}
self.display(request: request, timer: timer, token: accessToken, credentials: credentials) { result in
switch result {
case .success(let maybeSplash):
-- success-> Do the work
case .failure(let error):
---
completionHandler?(false, error)
return
}
}
}
)
Code for the publishers.
func credentials() -> AnyPublisher<Credentials, Error> {
return authentication.getSessionId().compactMap { $0 }
.combineLatest(authentication.getDirectedID().compactMap { $0 })
.first()
.setFailureType(to: CredentialsFetchError.self)
.timeout(.seconds(10), scheduler: DispatchQueue.global(), customError: { .timeout })
.tryMap { (sessionId, directedId) -> Credentials in
// use the sessionId and directedId to populate credentials object
return Credentials(....some attributes)
}
.mapError { $0 as Error }
.eraseToAnyPublisher()
}
func accessToken() -> AnyPublisher<AccessToken, Error> {
return authentication.accessToken.compactMap { $0 }
.first()
.setFailureType(to: CredentialsFetchError.self)
.timeout(.seconds(10), scheduler: DispatchQueue.global(), customError: { .timeout })
.mapError { $0 as Error }
.eraseToAnyPublisher()
}