I use Apollo iOS 0.8 with Xcode 9.3, Swift 4.1 and iOS 11, and initialise Apollo client instance like this:
import Apollo
// ... unrelated code skipped
let configuration = URLSessionConfiguration.default
if let token = keychain.accessToken {
// Add additional headers as needed
configuration.httpAdditionalHeaders = [
"Authorization": "Bearer \(token)"
]
}
let graphqlEndpoint = URL("https://sample-server-url/graphql")!
let client = ApolloClient(networkTransport:
HTTPNetworkTransport(url: graphqlEndpoint, configuration: configuration))
The application works well with all queries and mutations sent to the GraphQL server without a problem, except when the app is in background. As far as I know, with common NSURLSession
instance it can be easily solved by switching session configuration to URLSessionConfiguration.background(withIdentifier: "your-session-id")
.
But when I replace the line
let configuration = URLSessionConfiguration.default
with
let configuration = URLSessionConfiguration.background(withIdentifier: "your-session-id")
the app starts crashing with this error: Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.'
What's the best way to resolve this error when using Apollo GraphQL or is there any other way to communicate with a GraphQL server in background?
Apollo iOS provides a public NetworkTransport
protocol that allows overriding all networking interactions. An implementation can be provided as an argument to ApolloClient(networkTransport: NetworkTransport)
initialiser.
Suppose you have a NetworkTransport
implementation that wraps URLSession
implementation with background session configuration:
class BackgroundTransport: NetworkTransport {
public func send<Operation>(operation: Operation,
completionHandler: @escaping (GraphQLResponse<Operation>?, Error?) -> Void)
-> Cancellable where Operation: GraphQLOperation {
// ...
}
}
Then you can initialise ApolloClient
this way:
let graphqlEndpoint = URL("https://sample-server-url/graphql")!
let client = ApolloClient(networkTransport: BackgroundTransport(url: u))
BackgroundTransport
implementation can be as custom as needed, including using URLSession
delegate instead of completion handler blocks, as required for background session configuration.
If you use Alamofire in your app, you can also use ApolloAlamofire library that provides an implementation of NetworkTransport
with support for background URLSession
configuration and a few more features.