13. Write your first subscription


In this section, you will use subscriptions to get notified whenever someone books a flight 🚀! Subscriptions allow you to be notified in real time whenever an event happens on your server. The fullstack backend supports subscriptions based on WebSockets .

Write your subscription

Open your Sandbox back up, click on the Schema tab at the far left. In addition to queries and mutations, you will see a third type of operations, subscriptions. Click on subscriptions to see the tripsBooked subscription:

The definition of tripsBooked in the schema

This subscription doesn't take any arguments and returns a single scalar named tripsBooked. Since you can book multiple trips at once, tripsBooked is an Int. It will contain the number of trips booked at once or -1 if a trip has been cancelled.

Click the play button to the far right of tripsBooked to open the subscription in Explorer. Open a new tab, then check the tripsBooked button to have the subscription added:

The initial definition of the TripsBooked subscription

Again, rename your subscription so it's easier to find:

The subscription after rename

Click the Submit Operation button, and your subscription will start listening to events. You can tell it's up and running because a panel will pop up at the lower right where subscription data will come in:

The UI showing that it's listening for subscription updates

Test your subscription

Open a new tab in Explorer. In this new tab, add code to book a trip with a hard-coded ID:

GraphQL
1mutation BookTrip {
2  bookTrips(launchIds: ["93"]){
3    message
4  }
5}

Do not forget to include the authentication header. At the bottom of the Sandbox Explorer pane where you add operations, there's a Headers section:

Adding a login token to explorer

Click the Submit Operation button. If everything went well, you just booked a trip! At the top of the right panel, you'll see the success JSON for your your BookTrip mutation, and below it, updated JSON for the TripsBooked subscription:

Subscription success in Explorer

Continue booking and/or canceling trips, you will see events coming in the subscription panel in real time. After some time, the server might close the connection and you'll have to restart your subscription to keep receiving events.

Add the subscription to your project

Now that your subscription is working, add it to your project. Create an empty file named TripsBooked.graphql next to your other GraphQL files and paste the contents of the subscription. The process is similar to what you've already done for queries and mutations:

GraphQL
TripsBooked.graphql
1subscription TripsBooked {
2  tripsBooked
3}

Now run code generation in Terminal to generate the code for your subscription.

Configure your ApolloClient to use subscription

In Network.swift, you'll need to set up a transport which supports subscriptions in addition to general network usage. In practice, this means adding a WebSocketTransport which will allow real-time communication with your server.

First, at the top of the file, add an import for the ApolloWebSocket framework to get access to the classes you'll need:

Swift
Network.swift
1import ApolloWebSocket

Next, in the lazy declaration of the apollo variable, immediately after transport is declared, set up what you need to add subscription support to your client:

Swift
Network.swift
1private(set) lazy var apollo: ApolloClient = {
2    let client = URLSessionClient()
3    let cache = InMemoryNormalizedCache()
4    let store = ApolloStore(cache: cache)
5    let provider = NetworkInterceptorProvider(client: client, store: store)
6    let url = URL(string: "https://apollo-fullstack-tutorial.herokuapp.com/graphql")!
7    let transport = RequestChainNetworkTransport(interceptorProvider: provider, endpointURL: url)
8
9    let webSocket = WebSocket( // highlight-line
10        url: URL(string: "wss://apollo-fullstack-tutorial.herokuapp.com/graphql")!, // highlight-line
11        protocol: .graphql_ws // highlight-line
12    ) // highlight-line
13
14    let webSocketTransport = WebSocketTransport(websocket: webSocket) // highlight-line
15
16    let splitTransport = SplitNetworkTransport( // highlight-line
17        uploadingNetworkTransport: transport, // highlight-line
18        webSocketNetworkTransport: webSocketTransport // highlight-line
19    ) // highlight-line
20
21    return ApolloClient(networkTransport: splitTransport, store: store) // highlight-line
22}()

What's happening here?

  1. You've created a web socket with the server's web socket URL - wss:// is the protocol for a secure web socket.

  2. You've created a WebSocketTransport, which allows the Apollo SDK to communicate with the web socket.

  3. You've created a SplitNetworkTransport, which can decide whether to use a web socket or not automatically, with both the RequestChainNetworkTransport you had previously set up, and the WebSocketTransport you just set up.

  4. You're now passing the splitTransport into the ApolloClient, so that it's the main transport being used in your ApolloClient.

Now, you're ready to actually use your subscription!

Use your subscription

To use the subscription you created, go to LaunchListViewModel.swift and start by adding a new variable to hold the subscription:

Swift
LaunchListViewModel.swift
1@Published var launches = [LaunchListQuery.Data.Launches.Launch]()
2@Published var lastConnection: LaunchListQuery.Data.Launches?
3@Published var activeRequest: Cancellable?
4var activeSubscription: Cancellable? // highlight-line
5@Published var appAlert: AppAlert?
6@Published var notificationMessage: String?

Now, replace the TODO in the startSubscription() method with the following code:

Swift
LaunchListViewModel.swift
1func startSubscription() {
2    activeSubscription = Network.shared.apollo.subscribe(subscription: TripsBookedSubscription()) { [weak self] result in
3        guard let self = self else {
4            return
5        }
6
7        switch result {
8        case .success(let graphQLResult):
9            if let tripsBooked = graphQLResult.data?.tripsBooked {
10                self.handleTripsBooked(value: tripsBooked)
11            }
12
13            if let errors = graphQLResult.errors {
14                self.appAlert = .errors(errors: errors)
15            }
16        case .failure(let error):
17            self.appAlert = .errors(errors: [error])
18        }
19    }
20}

Next, update the TODO in the init() method to the following:

Swift
LaunchListViewModel.swift
1init() {
2    startSubscription()//highlight-line
3}

Notice in LaunchListView.swift there is already a line to handle displaying a view from the subscription:

Swift
LaunchListView.swift
1.notificationView(message: $viewModel.notificationMessage)

Test your subscription

Build and run the application, now whenever a trip is booked or cancelled (from either in the app detail view or from the Sandbox Explorer) you should see a small notification pop up at the bottom of the screen:

Subscription notification view

Congratulations, you've completed the tutorial!

More resources

There are way more things you can do with the Apollo iOS SDK, and the rest of this documentation includes info on more advanced topics like:

Feel free to ask questions by either joining our Discord server or joining the Apollo GraphQL Forum .