Как правильно использовать Apollo GraphQL на iOS с настройкой фоновой сессии?

Я использую Apollo iOS 0.8 с Xcode 9.3, Swift 4.1 и iOS 11 и инициализирую экземпляр клиента Apollo следующим образом:

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))

Приложение хорошо работает со всеми запросами и мутациями, отправленными на сервер GraphQL без проблем, кроме случаев, когда приложение находится в фоновом режиме. Насколько я знаю, с общим NSURLSession Например, это может быть легко решено путем переключения конфигурации сеанса на URLSessionConfiguration.background(withIdentifier: "your-session-id"),

Но когда я заменяю линию

let configuration = URLSessionConfiguration.default

с

let configuration = URLSessionConfiguration.background(withIdentifier: "your-session-id")

приложение начинает зависать с этой ошибкой: Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.'

Как лучше всего устранить эту ошибку при использовании Apollo GraphQL или есть какой-либо другой способ взаимодействия с сервером GraphQL в фоновом режиме?

1 ответ

Решение

Apollo iOS предоставляет общественности NetworkTransport протокол, который позволяет переопределять все сетевые взаимодействия. Реализация может быть предоставлена ​​в качестве аргумента ApolloClient(networkTransport: NetworkTransport) инициализатора.

Предположим, у вас есть NetworkTransport реализация, которая оборачивает URLSession реализация с настройкой фоновой сессии:

class BackgroundTransport: NetworkTransport {
    public func send<Operation>(operation: Operation,
    completionHandler: @escaping (GraphQLResponse<Operation>?, Error?) -> Void)
    -> Cancellable where Operation: GraphQLOperation {
    // ...
    }
}

Тогда вы можете инициализировать ApolloClient сюда:

let graphqlEndpoint = URL("https://sample-server-url/graphql")!
let client = ApolloClient(networkTransport: BackgroundTransport(url: u))

BackgroundTransport реализация может быть настолько индивидуальной, насколько это необходимо, включая использование URLSession делегировать вместо блоков обработчика завершения, как требуется для фоновой конфигурации сеанса.

Если вы используете Alamofire в своем приложении, вы также можете использовать библиотеку ApolloAlamofire, которая обеспечивает реализацию NetworkTransport с поддержкой фона URLSession конфигурация и еще несколько функций.

Другие вопросы по тегам