In this quickstart, we will introduce you to Daily's Client SDK for iOS by walking through the creation of a simple video call application. By the end of this walkthrough, you'll have a starting point for writing Daily-powered video apps for iOS with Swift.

This walkthrough will implement the following features:

  • Creating and joining a public Daily room
  • Asking for required application permissions
  • Displaying videos from local and remote room participants
  • Managing local microphone and camera input
  • Leaving the call

You can find the full codebase of this iOS app on GitHub.

Prerequisites

Before you get started, make sure you have a functioning iOS development environment, including the latest version of Xcode. You will also need a free Daily account.

If you want to test your app with a physical iOS device, make sure you have iOS 13.0 or newer, have enabled your device to run your own applications, and have enabled developer mode on your device.

Create a Daily room

Begin by navigating to Daily's developer dashboard and creating a new Daily room.

Create a room in the Daily Dashboard

Give your room a name and click the "Create room" button. All other options can be left at their defaults.

Make note of your Daily room URL. We'll be using it in the code shortly.

Create a new iOS project

Open Xcode and create a new project. Select the App template for your new project from the iOS tab:

Create a new project using the iOS template

In the project details window, enter your project and organization name. Select "Storyboard" in the "Interface" dropdown and click "Next":

Create a new project using the iOS template

You'll be prompted to pick a directory for your project. Once done, click "Create" to finish the process.

Add a dependency on Daily's Client SDK for iOS

With your new project created, you can add the Daily's iOS SDK as a dependency. When building an application using Xcode and Swift, you can use the Swift Package Manager to help you manage application dependencies.

In the top left corner of your Xcode window, press the File tab and select the "Add Packages..." option.

Add Daily dependencies to Xcode

In the search box at the top right hand corner, paste in the GitHub URL of Daily's iOS SDK repository: https://github.com/daily-co/daily-client-ios.git

A daily-client-ios package will appear:

Find the daily-client-ios package

Select "Branch" from the Dependency Rule dropdown and set the branch to main. Then, click "Add Package".

Xcode will now verify and load the package, then display a "Choose Package Products" dialog. Ensure "Daily" is selected and click "Add Package" again:

Add Daily dependencies to Xcode

Daily recommends using the latest stable version of the package that is compatible with your project requirements and your Swift version. Always check the release notes of the package to ensure there are no breaking changes that could impact your project.

In the project details page (which is shown by default), set the project's minimum deployment version to the version of iOS installed on your phone, which must be at least iOS 13.0.

Set the project's minimum deployment to iOS 13.0

Set application permissions

The application will need to be granted permissions to access the internet, use the device camera, and record and play audio.

Click on the parent Xcode project name in the project navigation sidebar:

Open project settings

Click on the "Build Settings" tab and then the "All" sub-tab:

Open build settings

In the "Filter" input box on the right, type "Camera". Once the "Privacy - Camera Usage Description" row appears, double click on the second column and enter: "Camera is necessary for transmitting video in a call":

Add camera usage description

Next, do the same with "Privacy - Microphone Usage Description", setting the description to "Microphone is necessary for transmitting audio in a call".

To ensure that audio will continue uninterrupted when your app is sent to the background, you also need to add the BackgroundModes capability. To do so, right-click on the Info.plist file. Choose "Open As -> Source Code" from the context menu. Then, copy and paste the XML code fragment below into the outermost parts of the file's body (<dict>...</dict>): add the following key and value to the top-level <dict>:

<key>UIBackgroundModes</key>
<array>
<string>voip</string>
</array>

To confirm your changes are in the right place, refer to the resulting Info.plist file on GitHub.

Define the user interface

After implementing permission handling, we can define the user interface for our application. The UI will support the following functionality:

  • Displaying participants' video
  • Presenting call controls for toggling the camera/microphone and leaving the meeting

Open ViewController.swift and declare the following UI elements within the ViewController class:

Next, we're going to configure the application layout in the main.storyboard file of the project. For that, you'll need some familiarity with the Xcode Interface Builder. Alternatively, you can copy the storyboard source from our existing demo repository.

Configuring the application layout through Xcode Interface Builder

If you're not already familiar with the Xcode Interface Builder, we've compiled some relevant resources below:

Adding objects to a storyboard:

Layout constraints:

Connecting storyboard objects to code:

Open the main.storyboard file and configure the required UI elements. These will be:

  • A UIButton to toggle the camera
  • A UIButton to toggle the microphone
  • A UIButton to leave the call
  • A UIStackView for the participant stack

Next, use the Xcode Objects Library to set the objects for the ViewController and configure their layout constraints.

Configure layout constraints

Now, connect the @IBOutlets you just defined in ViewController to their elements in the Storyboard:

Connect Outlets

Once the UI is configured, we're ready to build and run the application for the first time. To do so, click "Product -> Run" in the top application menu.

Once loaded, the application will prompt you to grant the necessary permissions. When permissions are granted, it should display the basic application interface you created:

Application loaded in simulator with a black screen at the top and call controls at the bottom

You won't see any video just yet because we haven't set up the call client or joined a Daily room. We'll do that next.

Setting up the call client

Now that the basics of the application are in place, we can shift our focus to joining and displaying participant videos.

The CallClient is the main interface into your Daily video call. It should be instantiated and retained for at least the duration of the video call session.

First, open ViewController.swift and import Daily:

Next, in the ViewController class, create a instance of the CallClient object, a VideoView for the local participant, and a dictionary of VideoView.

Finally, create a constant called roomURLString for your Daily room URL.

Add CallClient event listeners

With a CallClient instance created, we can set up our application to handle relevant events that occur during a video call. These events are emitted in response to actions like meeting participants joining, leaving, or being updated. We'll handle these events by adding an extension to have ViewController adopt the CallClientDelegate protocol.

Add the following declaration in ViewController.swift, underneath the original ViewController class:

In the ViewController viewDidLoad() method, set the call client's delegate to self:

To reflect accurate camera and microphone states in the local user's call controls, we'll create a function called updateControls() in the ViewController class. This function will update the state of the camera and microphone buttons. We'll also call this.updateControls() from the viewDidLoad() override method:

To make sure the controls are updated when input settings actually change, add a handler for the inputsUpdated event within the CallClientDelegate extension:

When the local particpant's view loads, we should add their video to the stack view in viewDidLoad(). Additionally, disable the idle timer to keep the device screen active while the app is running. The final viewDidLoad() method will now look as follows:

When remote participants join the Daily room, the app needs to display their video tracks. To do this, we'll listen for the participantJoined event in the CallClientDelegate extension:

Above, when a remote participant joins the room, a new VideoView instance is created to display their video. The video view's track property is set to the participant's video track. The new participant is then added to a dictionary of video views. Finally, UI updates are performed and the view is set to update its layout.

We should also handle update events for call participants, which will inform the app when a participant toggles their camera or microphone. To do so, we'll handle the participantUpdated event:

Above, using our previously created videoViews dictionary, we can find the video view of the remote participant being updated and modify it accordingly. If the participant being updated is local, we update their tracks using loclVideoView.

Finally, when a participant leaves the meeting we'll handle the participantLeft:withReason event:

After a participant leaves the room, their VideoView instance in the video views dictionary is removed.

Joining and leaving a Daily video call

With the CallClient instantiated set up to handle relevant Daily events, we're ready to have our app join a Daily room.

Create a new enterRoom() function within the ViewController class. Within it, invoke the call client's join() function, passing in the URL of the Daily room that you created earlier.

Call the new enterRoom() method from the view controller's viewDidAppear() method:

To let the user leave the meeting, connect @IBAction didTapLeaveRoom(_ sender: Any) to the leaveRoomButton. Then, invoke the the call client's leave() method:

Run the application. If you are running the app on actual hardware, you should see yourself as the local participant.

If you are running the application in the simulator, you should see a blank video view. This is because the simulator doesn't have access to your camera.

To test the app with a remote participant, open the room URL in your browser on any device. Once you've joined via the browser, the new participant's video should appear in the app view on your iOS device or simulator.

Remote video call participants in iOS simulator

Toggling microphone and camera states

Now that we have participant video being displayed in the app, we'll move on to implementing call controls.

Connect the @IBAction didTapToggleMicrophone(_ sender: Any) to the microphoneInputButton. Use the call client's setInputEnabled() instance method to toggle the microphone input:

Connect the @IBAction didTapToggleCamera(_ sender: Any) to the cameraInputButton. Use the call client's setInputEnabled() instance method to toggle the camera input:

Wrapping up

This quickstart walked you through the basics of using the Daily's Client SDK for iOS to build a simple video call app. You should now be familiar with:

  • How to create the app with appropriate dependencies and permissions
  • How to join a Daily room
  • How to display participant video in your Android app
  • How to toggle the local participant's microphone and camera
  • How to leave the Daily room

To delve further into our iOS SDK, please refer to our reference documentation or reach out to our support team