How to Build a Telemedicine App with Video and Chat for iOS
Tags: swift, ios, beginners, tutorial
Published: 2020-06-29 16:13:20

---
title: How to Build a Telemedicine App with Video and Chat for iOS
published: true
description: 
tags: swift, ios, beginners, tutorial
conver_image: https://i.imgur.com/MKoVio7.png
canonical_url: https://getstream.io/blog/telemedicine-video-chat-ios/
---

In this tutorial, we'll build the basis of a Telemedicine App for iOS using [Stream Chat](https://getstream.io/chat/), to deliver [fully featured chat components](https://getstream.io/tutorials/ios-chat/), and Dolby.io, to deliver quality audio and video. Both solutions provide [HIPAA compliance](https://getstream.io/blog/hipaa-compliant-chat-apps/). By the end, we'll have an application similar to the screenshots below. As a bonus, it's compatible with both light and dark mode.

![Image shows two screenshots, one from the chat screen with a small video overlay with the doctor, and another with a fullscreen video of the doctor](https://i.imgur.com/MKoVio7.png)

If you get lost during this tutorial, you can check the completed project in this [GitHub repo](https://github.com/getstream/telemedicine-app-ios). Let's get started with our telehealth app development!

## What is Stream Chat?
> Build real-time chat in less time. Rapidly ship in-app messaging with our highly reliable chat infrastructure. Drive in-app conversion, engagement, and retention with the Stream Chat messaging platform API & SDKs.
> - [Stream Chat & Messaging](https://getstream.io/chat/)

## What is Dolby.io's Client SDK?
> Dolby Interactivity APIs provide a platform for unified communications and collaboration. In-flow communications refers to the combination of voice, video, and messaging integrated into your application in a way that is cohesive for your end-users. This is in contrast to out-of-app communications where users must stop using your application and instead turn to third-party tools.
> - [Dolby.io Documentation](https://dolby.io/developers/interactivity-apis/client-sdk/overview)

## Requirements
- Xcode 11+
- iOS 13+
- A [Stream](https://getstream.io/accounts/signup/) account
- A [Dolby.io](https://dolby.io/organizations/register) account

## Set up project
### Create the Xcode project

First, we open Xcode and create a Single View App project.

![Screenshot shows a single view app created on Xcode 11](https://i.imgur.com/idlDOQA.png)

And make sure to select 'Storyboard' for the User Interface.

### Install dependencies

To install the [Stream Chat](https://github.com/getstream/stream-chat-swift) and [Dolby.io's Client SDK](https://github.com/voxeet/voxeet-sdk-ios) dependencies, we'll use [CocoaPods](https://cocoapods.org/). If you prefer Carthage, both frameworks support it as well.

In the folder where you saved the project, run `pod init` and add `StreamChat` and `VoxeetUXKit` to the `Podfile`. It should look similar to this:

{% gist https://gist.github.com/cardoso/b8e695db46653f8ba5c94bd2aa77c15d %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/b8e695db46653f8ba5c94bd2aa77c15d) - TIP: If you refresh the page, it may fix it!

After you do that, run `pod install`, wait a bit for it to finish, and open the project via the `.xcworkspace` that was created.

## Configure the Stream Chat dashboard

Sign up at [GetStream.io](https://getstream.io), create the application, and make sure to select development instead of production.

![Screenshot of a user creating a development application at GetStream.io](https://dev-to-uploads.s3.amazonaws.com/i/o6nhrm361eeh7qkhla8q.png)

To make things simple for now, let's disable both auth checks and permission checks. Make sure to hit save. When your app is in production, you should keep these enabled.

![Screenshot of skip auth checks and permission being enabled in a Stream App dashboard](https://dev-to-uploads.s3.amazonaws.com/i/ir0vtvh2rgowvy0lohn0.png)

You can see the documentation about authentication [here](https://getstream.io/chat/docs/tokens_and_authentication/?language=swift) and permissions [here](https://getstream.io/chat/docs/chat_permission_policies/?language=swift).  

Now, save your Stream credentials, as we'll need them to power the chat in the app. Since we disabled auth and permissions, we'll only really need the key for now, but in production, you'll use the secret in your backend to [implement proper authentication to issue user tokens for Stream Chat](https://getstream.io/docs/auth_and_permissions/), so users can interact with your app securely.

![Screenshot of credentials on stream dashboard](https://dev-to-uploads.s3.amazonaws.com/i/1bl76070ym1iiw211wef.png)

As you can see, I've blacked out my keys. You should make sure to keep your credentials safe.

## Configure the Dolby.io dashboard

Configuring the [Dolby.io](https://dolby.io) dashboard is simpler. Just create an account there, and it should already set up an initial application for you.

![Screenshot of credentials on dolby.io dashboard](https://dev-to-uploads.s3.amazonaws.com/i/fq770ahudm7o49ek3dmb.png)

Now, save your credentials, as we'll need them to power the audio and video streaming in the app. As with the Stream credentials, you use these for development. In production, you'll need to set up proper authentication. It's described in detail [here](https://dolby.io/developers/interactivity-apis/client-sdk/initializing#secure-authentication).

## Configure Stream Chat and Dolby.io's SDKs

The first step with code is to configure the Stream and Dolby SDK with the credentials from the dashboards. Open the `AppDelegate.swift` file and modify it, so it looks similar to this:

{% gist https://gist.github.com/cardoso/f7587d7989ab34029bac2b302ac9fa62 %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/f7587d7989ab34029bac2b302ac9fa62)

That code initializes the Dolby.io and Stream Chat SDKs with credentials you got in the previous two steps.

## Create the Join Screen

Let's start building the "Join" screen. This screen consists of two `UIButton` instances. One to join as the Patient, and the other to join as the Doctor. This is, of course, an oversimplification to make this tutorial short and get to the chat, audio, and video features faster. In your complete app, you'll need proper registration, database, and all that. For this tutorial, the screen will look similar to the screenshot below.

![Screenshot shows an app with two buttons, one to join as the patient, and the other to join as the doctor](https://i.imgur.com/S4crUXQ.png)

Go to the storyboard, select the default view controller, and click `Editor > Embed In > Navigation Controller`. That will place it under a navigation controller, which we'll use to navigate to the channel screen.

![Image shows storyboard with a JoinViewController embedded in a navigation controller](https://i.imgur.com/0QvlBGW.png)

Make sure to rename `ViewController` to `JoinViewController`, so you don't get confused later on. You can do this easily by right-clicking on `ViewController` in `ViewController.swift` and selecting `refactor`.

To make things simple, let's leave the storyboard like this and use only code from now on. To set up the two buttons, we need the following code in `JoinViewController.swift`:

{% gist https://gist.github.com/cardoso/9bc4bf7446c999a8491cd72aa7eb0787 %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/9bc4bf7446c999a8491cd72aa7eb0787)

That code sets up the views, the constraints, and the handlers we need. Let's start by extending `JoinViewController` to define `setupViews`:

{% gist https://gist.github.com/cardoso/9142eded9d7cd61c2d021b824c66bcc3 %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/9142eded9d7cd61c2d021b824c66bcc3)

That code will create the buttons and add them to the controller's view. Next, we need to define constraints between the three. Let's do this by extending `JoinViewController` to define `setupConstraints`:

{% gist https://gist.github.com/cardoso/c511a9d89d6f907d01be6691eed2cbc7 %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/c511a9d89d6f907d01be6691eed2cbc7)

That code will make sure the `patientButton` stays in the center of the screen and the `doctorButton` below it. Now we need to set up the handler for when the user presses the buttons. Let's do this again by extending the controller to define `setupHandlers`:

{% gist https://gist.github.com/cardoso/f43793f739991392d28a67ce399705ab %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/f43793f739991392d28a67ce399705ab)

That code will make it so when the user presses the button a `ConsultViewController` is created and set up for the doctor or patient, depending on which button was pressed. We'll create `ConsultViewController` in the next step.

## Create the Consult Screen

Now, let's create the screen where the patient and doctor will talk via chat and where they can begin a video call. We'll start by defining ConsultViewController. It will look similar to the screenshots below.

![Image shows two screenshots of a conversation in a chat screen, one from the perspective of the patient, and the other from the perspective of the doctor](https://i.imgur.com/vU579jV.png)

The first step is to create a ConsultViewController.swift file and paste the code below.

{% gist https://gist.github.com/cardoso/bdb9ecc570e966c700b3943e210b3273 %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/bdb9ecc570e966c700b3943e210b3273)

That code defines a subclass of ChatViewController, which provides most of the chat behavior and UI we need. It also defines the patient and doctor `User` objects and a `Channel` object between the two. These objects will be used to interact with the Stream API. On `viewDidLoad`, we also call `setupViews` and `setupHandlers` to set up the views and handlers needed. We'll define those functions next.

But, let's first define the `setupPatient` function that sets the current Stream Chat user as the patient, and the `setupDoctor` function that sets it as the doctor.

{% gist https://gist.github.com/cardoso/94ffcc5526a0979b103755d85ff9de07 %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/94ffcc5526a0979b103755d85ff9de07)

Now we define `setupViews` to set up the views we need.

{% gist https://gist.github.com/cardoso/628535f3838dbb477887f6c2e7cbf712 %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/628535f3838dbb477887f6c2e7cbf712)

Those functions will display a button which starts a call. For it to work, we'll need to define `setupHandlers` as well.

{% gist https://gist.github.com/cardoso/9f3ffaacb2254adc3cb5f170626a9c2a %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/9f3ffaacb2254adc3cb5f170626a9c2a)

Those functions set `callButtonPressed` as the function to be called when the call button is pressed, which in turn calls `startCall`, which we define next.

{% gist https://gist.github.com/cardoso/9946fda83650e60113d764a7e3198226 %}
(dev.to might be showing a different snippet due to a bug, if so link is here: https://gist.github.com/cardoso/9946fda83650e60113d764a7e3198226)

Finally, that function uses the Dolby.io SDK to start a conference call.

## Configure usage descriptions

If you run the app now, you'll be able to chat, but pressing the call button will cause the application to crash. That happens because we need to configure the usage descriptions for microphone and video in the `Info.plist` file. To do this, just open `Info.plist` and set the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` keys as pictured below. 

![Image shows the Info.plist file with the two usage descriptions defined](https://i.imgur.com/Tk1n99o.png)

Finally, we open the app in two devices, and, from the chat, we can start a call.

![Image shows two screenshots, one from the chat screen with a small video overlay with the doctor, and another with a fullscreen video of the doctor](https://i.imgur.com/MKoVio7.png)

## Wrapping up

Congratulations! You've built the basis of a functioning telemedicine app with Stream Chat and Dolby.io. I encourage you to browse through [Stream Chat's docs](https://getstream.io/chat/docs/introduction/?language=swift), [Dolby.io's docs](https://dolby.io/developers/interactivity-apis/client-sdk/overview), and experiment with the project you just built. If you're interested in the business side of things, read about how [Stream Chat provides HIPAA compliance](https://getstream.io/blog/hipaa-chat/) and how [Dolby.io provides HIPAA compliance](https://dolby.io/pricing/interactivity-apis/). Good luck on your telemedicine app development!