Subscriptions
Subscriptions are long-lived GraphQL read operations that can update their response over time, enabling clients to receive new data as it becomes available.
Apollo iOS supports subscriptions over the following protocols:
- WebSocket, including multiplesubprotocols
- HTTP, usingchunked multipart responses(version 1.1.0 and later)
You must use whichever protocol is supported by your GraphQL endpoint.
Enabling support
To support GraphQL subscriptions, you need to initialize your ApolloClient
instance with a NetworkTransport
WebSocket
To use Apollo iOS with WebSocket-based subscriptions, you need to install the optional ApolloWebSocket
library. This library includes two classes that conform to the NetworkTransport
protocol
- sends all operations (including queries and mutations) over WebSocket.
WebSocketTransport
- maintains a
SplitNetworkTransport
instance, along with anWebSocketTransport
instance (usuallyUploadingNetworkTransport
). This provides a single network transport that uses HTTP for queries and mutations and WebSocket for subscriptions.RequestChainNetworkTransport
SplitNetworkTransport
is recommended for most use cases, because it enables you to retain a single NetworkTransport
setup that avoids issues caused by using multiple client objects.
Here's an example of setting up an ApolloClient
that uses a SplitNetworkTransport
to support all operation types:
WebSocket subprotocols
Apollo iOS supports the following WebSocket subprotocols for subscriptions:
- , which is implemented in the
graphql-ws
subscriptions-transport-wsandAWS AppSynclibraries. (⚠️ This protocol is not actively maintained!) - , which is implemented in the
graphql-transport-ws
graphql-wslibrary.
Note: These protocols are not cross-compatible. You need to use whichever protocol is supported by your GraphQL endpoint. All WebSocket
initializers enable you to specify which protocol to use (expand the code block above for an example).
Providing authorization tokens
In a standard HTTP operation, if authentication is necessary an Authorization
header is often sent with requests. However, with WebSocket, this can't be sent with every payload because a persistent connection is required.
For WebSocket, the connectingPayload
provides the parameters you would typically specify in your request headers.
Note that this must be set when the WebSocketTransport
is created. If you need to update the connectingPayload
, you need to recreate the client using a new webSocketTransport
.
let webSocketTransport: WebSocketTransport = {let url = URL(string: "ws://localhost:8080/websocket")!let webSocketClient = WebSocket(url: url, protocol: .graphql_transport_ws)let authPayload: JSONEncodableDictionary = ["authToken": myAuthToken]let config = WebSocketTransport.Configuration(connectingPayload: authPayload)return WebSocketTransport(websocket: webSocketClient, config: config)}()
HTTP
The default NetworkTransport
for Apollo iOS is the RequestChainNetworkTransport
1.1.0
and later, this transport supports subscriptions over HTTP, with no additional configuration required.
See the instructions for
Generating and executing
Apollo iOS supports subscriptions via GraphQLSubscription
protocol.
subscription ReviewAdded {reviewAdded {idstars}}
After you generate these classes, you can execute subscriptions using ApolloClient.subscribe(subscription:)
with a NetworkTransport
let subscription = client.subscribe(subscription: ReviewAddedSubscription()) { result inguard let data = try? result.get().data else { return }print(data.reviews.map { $0.stars })}
Note: GraphQL subscriptions are distinct from
Canceling a subscription
It's important to cancel a subscription connection whenever you're done with it. As long as a subscription is active, it maintains a connection to the server, and its resultHandler
completion block is retained. This can create memory leaks and reduce your application's performance.
When you call ApolloClient.subscribe(subscription:)
an opaque Cancellable
is returned. You can cancel the subscription by calling cancel()
on the returned Cancellable
. This terminates the connection to the server and releases the resultHandler
completion block.
A subscription's cancellation object does not cancel itself when it's deallocated! Make sure to cancel()
it yourself. A class
can ensure any subscriptions it manages are canceled when it's released by using its deinitializer:
class ReviewViewController {let client: ApolloClient!private var subscription: Cancellable?func subscribeToReviews() {// Keep a reference to the subscription's cancellation object.self.subscription = client.subscribe(subscription: ReviewAddedSubscription()) { [weak self] result in// Handle each update from the subscription.}}deinit {// Make sure the subscription is cancelled, if it exists, when this object is deallocated.self.subscription?.cancel()}}