如何在iOS上正确使用Apollo GraphQL和后台会话配置?

时间:2018-04-29 17:44:20

标签: ios swift graphql apollo apollo-ios

我在Xcode 9.3,Swift 4.1和iOS 11中使用Apollo iOS 0.8,并初始化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 个答案:

答案 0 :(得分:2)

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库,该{{3}}库提供NetworkTransport的实施,支持后台URLSession配置和更多功能