Call to get publishers never returns in combine swift

713 Views Asked by At

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()
}
0

There are 0 best solutions below