12 Weeks as an iOS Developer Apprentice
Crunchtime. The last week of the apprentice projects.
One of my tasks this week was to create a live user list for Prezto, so that a presenter could see who was present and ready to view their presentation.
Pusher had been chosen for us to work with for sending notifications from the presenter to the viewer and vice versa. Pusher is a hosted real-time messaging service with APIs, developer tools and open source libraries.
PusherSwift is the Pusher-recommended Swift library. Unfortunately, the iOS documentation on Pusher’s website references libPusher, an objective-c pusher library. So stick to the documentation in the PusherSwift github readme or the cocoapods docs to avoid any confusion.
To create a live user list, you create a “presence channel” via Pusher. Any user that subscribes to the presence channel can be notified when other members join (subscribe) or leave (unsubscribe from) the channel.
Here are the steps I took in creating and subscribing to a presence channel.
- Step 1
Create a Pusher object with PusherClientOptions and connect to Pusher
I first created a PusherClient class to manage all of my Pusher needs and, in order to keep my Pusher connection alive throughout the app, I created a shared instance or singleton of my PusherClient.
Initializing a Pusher object requires your Pusher app key and “PusherClientOptions”.
For a presence pusher you must authenticate your users and do so via your app secret or an authentication endpoint specified in the PusherClientOptions “authMethod”. It is recommended that you use an auth endpoint over your app secret.
Depending on how your backend is set up, you may need to build a request with the authentication endpoint to include any necessary parameters or header fields, etc. If so, you must create an object that conforms to the AuthRequestBuilderProtocol to create your authorization request.
Line 9 is the only required method of the AuthRequestBuilderProtocol, and it’s inside this function that you must specify your request.
My unique request includes my presence channel URL, HTTPMethod, HTTPBody with my required parameters, and HTTPHeaderFields including the user auth token.
The socketID is provided by the PusherSwift SDK when making the authorization request.
I created a convenience init to include a path to the URL endpoint so that I could use this method to build a request for more than one channel.
I added the above method to my PusherClient so that I could initialize my presencePusher with my PusherClient sharedInstance and connect to Pusher in one swift move in the appDelegate:
- Step 2
Subscribe to the presence channel
Both the viewer and the presenter must subscribe to the presence channel and we then bind to subscription status events to verify whether or not we’ve successfully subscribed.
Here’s a simple enum to handle the result of our binding requests:
Right now, we’re only passing back some info regarding errors. This can be further refined down the road.
For now the viewer only needs to announce their presence and verify whether or not we have successfully subscribed to the channel.
On the presenter-side though, we also want to pass back any members/participants who may have already joined the presence channel.
The presenter will not recieve a notification for any members that are already subscribed when the presenter joins the channel. They won’t set off a notification as being newly subscribed.
So when we bind to the presence channel subscription status we can pick them up and pass them along.
Inside the function on line 11, we bind to both the “pusher:subscription_succeeded” and “pusher:subscription_error” events. Here we can get info regarding our status and if successful it will include info about any members who have already joined the channel.
It is also important to note that you will not be able to subscribe to a channel unless you have successfully connected to Pusher first.
The member info that is passed to us as the “status” is in dictionary form and includes the subscriber’s info as well.
We want to pass back PresenceChannelMember objects, and we don’t want to include the subscriber.
The folllowing method handles this.
All PresenceChannelMembers have a unique userID and userInfo as specified on the backend. The userInfo is a dictionary that includes the user’s name as provided by their login info via Google or Facebook.
Invoke the methods above wherever you want to announce a participant’s presence or recieve notifications of any participants joining or leaving the presence channel.
I can announce a viewer’s presence with one line, including the unique channel name that we assign to each Prezto:
When I first subscribe as a presenter, I will add any members that were already subscribed to the viewModel’s participants list and reload the tableView data.
The viewModel takes care of creating a list of user names from the PresenceChannelMember objects it receives.
When subscribing in the method above I must provide closures to handle the notifications received whenever any participants join or leave the channel.
Here again my viewModel takes care of the dirty work and the tableView is reloaded. Thank you viewModel.
Aaaaaaaaaaaaaaand that’s a wrap.