Suggestions

close search

Back to Tutorials

Set up a Basic iOS Client (Swift)

This tutorial will walk you through the steps of setting up a basic iOS client that uses OpenTok.

Overview

All OpenTok applications require both a client and a server component. The client-side code is what loads in an end-user's iOS device and handles the majority of OpenTok functionality, including connecting to the session, publishing audio-video streams to the session, and subscribing to other clients’ streams. For more information on clients, servers, and sessions, see OpenTok Basics.

In this tutorial, you will be utilizing the OpenTok iOS SDK, OpenTok's client-side library for iOS devices, to quickly and easily build a real-time interactive video application.

Note: The code in this tutorial is written in Swift. There is also a tutorial with the code written in Objective-C.

Here are the items that will be covered in this tutorial:

Estimated completion time: 25 mins

Want to skip this tutorial? You can jump to the completed iOS Swift client code in the Basic-Video-Chat folder of our Swift sample app repo on GitHub. The repo includes a README with documentation for running and exploring the code.

Requirements

To complete this tutorial, you'll need:

Step 1: Creating a new project

  1. Open Xcode and create a new project.

  2. Select Single View Application as the template.

  3. Select Swift as the language for the app code.

Step 2: Adding the OpenTok library

Follow the steps below to use CocoaPods to add the OpenTok library and its dependencies to your app. If you would prefer not to use CocoaPods, follow these instructions for using the SDK.

  1. In the Terminal, navigate to the root directory of your project and enter:

    pod init

    This creates a Podfile at the root of your project directory.

  2. Edit the Podfile and add the following line after the comment that says # Pods for [YourProjectName] (The podfile will not be visible in your XCode project, so you will need to open it from the project folder directly):

    pod 'OpenTok'
  3. Save changes to the Podfile.

  4. Open your project's root directory in the Terminal and type:

    pod install
  5. Close your project in Xcode. Then reopen your project by double-clicking the new .xcworkspace file in the Finder (in the root directory of your project).

For camera and microphone access you need to modify the Info.plist file:

  1. In the lefthand navigator panel in Xcode, click the project file (with the name of your project) to open the center project panel.

    To the left of the General tab in the project panel, you should see your project name. If the name is something different from your project (such as [YourProjectName]Tests), click on it and set the target to your project name.

  2. Inside the panel, switch to the Info tab.

  3. Expand the Custom iOS Target Properties section if it’s collapsed

  4. Mouse over any key and click the + button to add a new key. Add a Privacy - Camera Usage Description key and assign it the following string:

    $(PRODUCT_NAME) uses the camera.

    Then click the + button to add a new Privacy - Microphone Usage Description key and assign it the following string:

    $(PRODUCT_NAME) uses the microphone.

    The app displays these strings when the application first accesses the camera and microphone.

    (These security features were added in iOS 10.)

Add the OpenTok library to the view controller.

Step 3: Setting up authentication

In order to connect to an OpenTok session, the client will need access to some authentication credentials — an API key, session ID, and token. In a production application, these credentials should be generated by a server, but to speed things up we will just hard code the values for now:

  1. Start by copying the following code block and adding it to your ViewController.swift file:

    // Replace with your OpenTok API key
    var kApiKey = ""
    // Replace with your generated session ID
    var kSessionId = ""
    // Replace with your generated token
    var kToken = ""
    

    Add these lines before the class ViewController declaration.

  2. Adjust the code by hard coding the values for the kApiKey, kSessionId and kToken.

    To do this, log into your TokBox Account, either create a new standard project or use an existing standard project, then go to your project page and scroll down to the Project Tools section. From there, you can generate a session ID and token manually. Use the project's API key along with the session ID and token you generated.

Important: You can continue to get the session ID and token values from your Account during testing and development, but before you go into production you must set up a server. We will discuss this in Next steps at the end of this tutorial.

For more information on sessions, tokens, and servers, check out OpenTok Basics.

Step 4: Connecting to the session

Next, we will connect to the OpenTok session. You must do this before you can publish your audio-video stream to the session or view other participants streams.

  1. Add a session property to the ViewController class:

    class ViewController: UIViewController
       var session: OTSession?
    

    The OTSession class is defined in the OpenTok iOS SDK. It represents an OpenTok session and includes methods for interacting with the session.

  2. Add a method to instantiate the OTSession object and call its [OTSession connectWithToken: error:] method. Then you can call it in viewDidLoad:

    override func viewDidLoad() {
       super.viewDidLoad()
       connectToAnOpenTokSession()
    }
    
    func connectToAnOpenTokSession() {
        session = OTSession(apiKey: kApiKey, sessionId: kSessionId, delegate: self)
        var error: OTError?
        session?.connect(withToken: kToken, error: &error)
        if error != nil {
            print(error!)
        }
    }
    

    The OTSession() constructor takes three parameters:

    • Your OpenTok API key
    • The session ID
    • The object that implements the OTSessionDelegate protocol

    The connect() method of the session object connects the client application to the OpenTok session. You must connect before sending or receiving audio-video streams in the session (or before interacting with the session in any way). The connect() method takes two parameters:

    • token is the authentication token for this client to connect to the OpenTok session.

    • error is set to an OTError object if an error occurs synchronously when calling the method.

  3. Next we will implement methods of the OTSessionDelegate protocol. Add the following code to the end of the ViewController.swift file, after the closing bracket of the ViewController class:

    // MARK: - OTSessionDelegate callbacks
    extension ViewController: OTSessionDelegate {
       func sessionDidConnect(_ session: OTSession) {
           print("The client connected to the OpenTok session.")
       }
    
       func sessionDidDisconnect(_ session: OTSession) {
           print("The client disconnected from the OpenTok session.")
       }
    
       func session(_ session: OTSession, didFailWithError error: OTError) {
           print("The client failed to connect to the OpenTok session: \(error).")
       }
       func session(_ session: OTSession, streamCreated stream: OTStream) {
           print("A stream was created in the session.")
       }
    
       func session(_ session: OTSession, streamDestroyed stream: OTStream) {
           print("A stream was destroyed in the session.")
       }
    }
    

    This protocol includes methods for handling events related to the session:

    • When the client connects to the OpenTok session, the sessionDidConnect(_:) method is called.

    • If the client fails to connect to the OpenTok session, an OTError object is passed into the session(_: didFailWithError:) method.

    • When the client disconnects from the OpenTok session, the sessionDidConnect(_:) method is called.

    • When another client publishes a stream to the OpenTok session.

    • When another client stops publishing a stream to the OpenTok session.

    For now, the app prints to the debugger console when any of these events occur.

Debug your application. If the app successfully connects to the OpenTok session, the the sessionDidConnect(_:) method print to the debug console.

Step 5: Publishing a stream to the session

When the app connects to the OpenTok session, we want it to publish an audio-video stream to the session, using the device's camera and microphone:

  1. Add a publisher property to the ViewController class:

    class ViewController: UIViewController {
       var session: OTSession?
       var publisher: OTPublisher?
    

    The OTPublisher class is defined in the OpenTok iOS SDK. It uses the device's camera and microphone, to publish a stream OpenTok session.

  2. Modify the implementation of the sessionDidConnect(_:) method to include code to publish a stream to the session:

    func sessionDidConnect(_ session: OTSession) {
        print("The client connected to the OpenTok session.")
    
        let settings = OTPublisherSettings()
        settings.name = UIDevice.current.name
        guard let publisher = OTPublisher(delegate: self, settings: settings) else {
            return
        }
    
        var error: OTError?
        session.publish(publisher, error: &error)
        guard error == nil else {
            print(error!)
            return
        }
    
        guard let publisherView = publisher.view else {
            return
        }
        let screenBounds = UIScreen.main.bounds
        publisherView.frame = CGRect(x: screenBounds.width - 150 - 20, y: screenBounds.height - 150 - 20, width: 150, height: 150)
        view.addSubview(publisherView)
    }
    

    When the app connects to a session, it initializes an instance of the OTPublisher, defined in the OpenTok iOS SDK. The constructor takes one parameter: the object that implements the OTPublisherDelegate protocol.

    The code then passes the OTPublisher object in as a parameter of the session.publish() method. This method publishes an audio-video stream to the OpenTok session, using the camera and microphone of the iOS device. (Note that in the Xcode simulator, the OpenTok iOS SDK uses a test video when publishing a stream.)

    The OTPublisher object has a view property, which is a UIView object. This view displays the video captured from the device's camera. The code adds this view as a subview of the main ViewController's view.

  3. Next we will implement methods of the OTPublisherDelegate protocol. This protocol includes methods for handling events related to the publisher. Add the following code to the end of the ViewController.swift file, after the closing bracket of the OTSessionDelegate extension:

    // MARK: - OTPublisherDelegate callbacks
    extension ViewController: OTPublisherDelegate {
       func publisher(_ publisher: OTPublisherKit, didFailWithError error: OTError) {
           print("The publisher failed: \(error)")
       }
    }
    
    • If the client fails to publish to the OpenTok session, an OTError object is passed into the publisher(_: didFailWithError:) method.

Debug your application. If the app successfully connects to the OpenTok session, it will publish a stream to the session, and you will see the publisher's video in the app.

Step 6: Subscribing to other clients' streams

Finally, we want clients to be able to subscribe to (or view) other clients' streams in the session:

  1. Add a subscriber property to the ViewController class:

    class ViewController: UIViewController {
       var session: OTSession?
       var publisher: OTPublisher?
       var subscriber: OTSubscriber?
    

    The OTSubscriber class is defined in the OpenTok iOS SDK. It uses the device's camera and microphone, to subscribe a stream OpenTok session.

  2. Modify the implementation of the session(_: streamCreated) method (one of the OTSessionDelegate callbacks) to include code to subscribe to other clients' streams the session:

    func session(_ session: OTSession, streamCreated stream: OTStream) {
        subscriber = OTSubscriber(stream: stream, delegate: self)
        guard let subscriber = subscriber else {
            return
        }
    
        var error: OTError?
        session.subscribe(subscriber, error: &error)
        guard error == nil else {
            print(error!)
            return
        }
    
        guard let subscriberView = subscriber.view else {
            return
        }
        subscriberView.frame = UIScreen.main.bounds
        view.insertSubview(subscriberView, at: 0)
    }
    

    When another client publishes a stream to a session, this method is called, and an OTStream object is passed in. The OTStream class is defined in the OpenTok iOS SDK, and it represents an audio-video stream in the OpenTok session. The code initializes an instance of the OTSubscriber class, defined in the OpenTok iOS SDK. The OTSubscriber() constructor takes two parameters: The OTStream object (for the stream you want to view) and the object that implements the OTSubscriberDelegate protocol.

  3. Next we will implement methods of the OTSubscriberDelegate protocol. This protocol includes methods for handling events related to the subscriber. Add the following code to the end of the ViewController.swift file, after the closing bracket of the OTPublisherDelegate extension:

    // MARK: - OTSubscriberDelegate callbacks
    extension ViewController: OTSubscriberDelegate {
       public func subscriberDidConnect(toStream subscriber: OTSubscriberKit) {
           print("The subscriber did connect to the stream.")
       }
    
       public func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) {
           print("The subscriber failed to connect to the stream.")
       }
    }
    
    • When the client connects to the OpenTok session, the subscriberDidConnect(_:) method is called.

    • If the client fails to connect to the OpenTok session, an OTError object is passed into the subscriber(_: didFailWithError:) method.

Step 7: Running the app

Now that you're code is complete, you can run the app in the XCode emulator. This will create a simulated publisher video — since the emulator cannot access your webcam, the publisher video will display a spinning teapot graphic instead of your camera feed.

To add a second publisher (which will display as a subscriber in your emulator), either run the app a second time in a connected iOS device or use the OpenTok Playground to connect to the session in a supported web browser (Chrome, Firefox, or Internet Explorer 11) by following the steps below:

  1. Go to OpenTok Playground (must be logged into your Account)

  2. Select the Join existing session tab

  3. Copy the session ID you used in your ViewController.m file and paste it in Session ID input field

  4. Click Join Session

  5. On the next screen, click Connect, then click Publish Stream

  6. You can adjust the Publisher options (not required), then click Continue to connect and begin publishing and subscribing

At this point you should see the stream being published from your webcam as well as the stream being published by the emulator. Returning to the emulator, you should also see the new publisher displayed on the emulated screen.

Congratulations! You've finished the 'Set up a Basic iOS Client (Swift)' tutorial.
You can continue to play with and adjust the code you've developed here for the client-side of your application, but keep in mind that you'll need to implement the server component of your application before going to production (see Setting up your server below).

You can view a completed version of this sample app in the Basic-Video-Chat folder of the opentok-ios-sdk-samples-swift repo on GitHub. This completed version adds code to load the session ID, token, and API key from a web service (instead of using hard coded values).

Setting up your server

In the tutorial above, we had you hard code your authentication credentials. However, for a production application, the sessionId and token values in your code must be generated by your app server and passed to the client. Here are a couple of reasons why you don't want hard coded credentials in your production app:

You can continue testing your application with hard coded values, but when you're ready to set up a server there are a number of ways to do so:

Server Option 1 — Launch a simple REST server on Heroku with one click

This is probably the fastest way to get a server up and running, but it has limited functionality. Simply click the Heroku button below, at which point you'll be sent to Heroku's website and prompted for your OpenTok API Key and API Secret — you can get these values on your project page in your TokBox Account. If you don't have a Heroku account, you'll need to sign up (it's free).

Deploy

Want to explore the code? The button above launches server code from the learning-opentok-php GitHub repo. Visit the repo to review the code as well as additional documentation — you can even fork the repo and make changes before deploying.

Prefer Node.js? Visit the learning-opentok-node repo for the same functionality using Node.js (including Heroku deploy button.)

Once the server is deployed on Heroku, you'll need to add a few lines to your client-side code. Instead of calling connectToAnOpenTokSession directly, you'll need to make a networking call to the path /session on your server to fetch valid OpenTok credential first.

Copy the following code and use it to replace viewDidLoad in your ViewController.m file:

override func viewDidLoad() {
    super.viewDidLoad()

    let configuration = URLSessionConfiguration.default
    let session = URLSession(configuration: configuration)
    let url = URL(string: <#https://YOURAPPNAME.herokuapp.com/session#>)
    let dataTask = session.dataTask(with: url!) {
        (data: Data?, response: URLResponse?, error: Error?) in

        guard error == nil, let data = data else {
            print(error!)
            return
        }

        let dict = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [AnyHashable: Any]
        kApiKey = dict?["apiKey"] as? String ?? ""
        kSessionId = dict?["sessionId"] as? String ?? ""
        kToken = dict?["token"] as? String ?? ""
        self.connectToAnOpenTokSession()
    }
    dataTask.resume()
    session.finishTasksAndInvalidate()
}

You'll need to replace https://YOURAPPNAME.herokuapp.com with your actual Heroku app url — you can find this on your app page on the Heroku website.

The code above makes a request to the /session endpoint (https://YOURAPPNAME.herokuapp.com/session), which should return an HTTP response that includes the session ID, the token, and API key formatted as JSON data, which is then assigned to the corresponding variables.

This /session endpoint will always return the same session ID, but will produce a new token each time it's called — this results in each client receiving a unique token.

Server Option 2 — Build from scratch using the server SDKs

Option 1 uses REST endpoints for transmitting credentials to the client, but that's only one of many ways to implement a server with OpenTok. If you want a greater level of customization, you can review OpenTok's Server SDK documentation for the server-side language of your choice (available for PHP, Node.js, Java, .NET, Python and Ruby). The documentation goes over the setup process and the various methods you'll need to generate sessions and tokens, as well as other server-side functionality.