> For the complete documentation index, see [llms.txt](https://documentation.sceenic.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.sceenic.co/synchronization-sdk/tutorials/ios/ios-swift.md).

# iOS - Swift/Objective-c

## Overview <a href="#overview" id="overview"></a>

Follow this step-by-step tutorial to implement the video playback Synchronization SDK.

While the client-side SDK will take care of most of the functionality, in order to make this sample application work, you will need to use the API\_KEY provided to you.

* Full code samples can be found here&#x20;
  * [Swift code samples](https://bitbucket.org/svmt/synch-ios-swift/src/master/)
  * [Objective-c adapter code samples](https://bitbucket.org/svmt/sample-synchsdk-ios-objc/src/master/)

## Requirements <a href="#requirements" id="requirements"></a>

To complete this guide successfully the following prerequisites are required:

* A Sceenic account
* [Xcode](https://itunes.apple.com/ua/app/xcode/id497799835?mt=12)
* Access key for Synch SDK
* iOS version 11 or higher

## Authentication <a href="#authentication" id="authentication"></a>

An `Access Token` is needed in order to allow a client to connect to a sync group.

{% hint style="danger" %}
**Note:** It is important that the client application does not request an Access Token directly from the backend. By doing that you risk exposing the API\_TOKEN and API\_SECRET.
{% endhint %}

### Acquiring an Access Token <a href="#acquiring-an-access-token" id="acquiring-an-access-token"></a>

{% tabs %}
{% tab title="cUrl(Bash)" %}

```bash
curl -iL --request GET --url https://YOUR_CAS_URL/sync/token --header 'auth-api-key: API_KEY'   --header 'auth-api-secret: API_SECRET'
```

{% endtab %}
{% endtabs %}

The `Access Token` is a JWT token - more about jwt you can read - [here](https://en.wikipedia.org/wiki/JSON_Web_Token).

A successful response will look like that:

```
{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...."
}
```

{% hint style="info" %}
You can get your API\_KEY and API\_SECRET in your private area, [here](https://media.sceenic.co/).
{% endhint %}

{% hint style="warning" %}
**Note:** Every Sync Token corresponds to one specific sync group only. To allow two different clients to connect to the same group, the clients need to use the same `Access Token`.
{% endhint %}

## &#x20;Create a project <a href="#create-a-project" id="create-a-project"></a>

* Open Xcode and create a new project
* Choose a Single View application
* Configure your product organization, bundle, and team names
* Set the application location on your computer and press “create”

## Adding iOS SynchSDK library to the project

You can drag SynchSDK.framework to the project tree and use this library manually.

### Cocoapods <a href="#cocoapods" id="cocoapods"></a>

* Download library ([Private area](https://media.sceenic.co/)) package and unpack it
* Create a folder with the name "SynchSDK" at the root of the project
* Copy all files ("SynchSDK.framework","SynchSDK.podspec") to the folder
* You can use [Cocoapods](https://cocoapods.org/) to install SynchSDK by adding it to your Podfile\
  `pod 'SynchSDK', :path => './SynchSDK'`
* \[When using the Objective-c adapater] - do the following extra steps
  * Create a folder with the name "SynchSDK" at the root of the project
  * Copy all files ("SynchSDKAdapter.framework","SynchSDKAdapter.podspec") to the folder
  * You can use [Cocoapods](https://cocoapods.org/) to install SynchSDK by adding it to your Podfile\
    `pod 'SynchSDKAdapter', :path => './SynchSDKAdapter'`

## Instantiating the SDK

* Initialize SynchSDK object:

{% tabs %}
{% tab title="Swift" %}

```swift
let synchSDK = SyncSDK?

do {
    synchSDK = try SyncSDK(accessToken: token, userName: userName) //token - authorization token, username - name of user
    synchSDK.attachListener(self)// self - SynchListener object
} catch {
    print(error)// error is SynchTokenError
    //fallback logic
}
    
```

{% endtab %}

{% tab title="Objective-c adpater" %}

```objectivec
@interface YourViewController () <SynchListenerAdapter>
@property (nonatomic, strong) SynchSDKAdapter* synch;
end;

- (void)viewDidLoad {
    [super viewDidLoad];
    NSError* err = nil;
    _synch = [[SynchSDKAdapter alloc] initWithAccessToken: token username:@"userName" error: &err];
    if (err != NULL) {
        NSLog(@"%@", err);
        //fallbacklogic
    } 
    [_synch attachListener: self];
    
```

{% endtab %}
{% endtabs %}

* Start synchronization - To start using the SynchSDK object you will require a SynchSdk’s URL and a valid Access Token to be available before connecting.

{% tabs %}
{% tab title="Swift" %}

```swift
synchSDK.startSynchronize()
```

{% endtab %}

{% tab title="Objective-c adpater" %}

```objectivec
[synch startSynchronize];
```

{% endtab %}
{% endtabs %}

* Stop synchronization

{% tabs %}
{% tab title="Swift" %}

```swift
synchSDK.stopSynchronize()
```

{% endtab %}

{% tab title="Objective-c adpater" %}

```objectivec
[synch stopSynchronize];
```

{% endtab %}
{% endtabs %}

## Managing synchronization logic

To manage the synchronization logic we provided several callbacks and will allow you to customize the interactions you need.

* The SynchListener interface, which the StreamView implements in the sample application, will allow you to control the flow of logic of the Synchronization you are managing

{% tabs %}
{% tab title="Swift" %}

```swift

extension StreamView: SynchListener{
    func onClientList(clientList: [Client]) {
        // remote client joined to the group, update ui using adapter
    }
    
    func onSetPlaybackRate(rate: Float) {
        // setting playback rate
    }
    
    func onPlaybackFromPosition(position: Int, participantId: String) {
        // playback from position
    }
    
    func onGetPlayerPosition() -> Int {
        // getting player position
    }
    
    func onGetPlaybackRate() -> Float {
        // getting playback rate
    }
    
    func onSyncInfo(accuracy: Float, delta: Int) {
        // information about synchronization's accuracy and delta
    }
    func onResumePlay(participantId: String) { 
        player?.play()
    }
    
    func onPause(participantId: String) {
        player?.pause()
    }
    
}
```

{% endtab %}

{% tab title="Objective-c adapter" %}

```objectivec
- (void)onClientListWithClientList:(NSArray<ClientAdapter *> * _Nonnull)clientList {
    // remote client joined to the group, update ui using adapter
}

- (float)onGetPlaybackRate {
     // setting playback rate
}

- (NSInteger)onGetPlayerPosition {
        // getting player position
}

- (void)onPlaybackFromPositionWithPosition:(NSInteger)position participantId:(NSString*) participantId {
   // playback from position
}

- (void)onSetPlaybackRateWithRate:(float)rate {
     // getting playback rate
}

- (void)onSyncInfoWithAccuracy:(float)accuracy delta:(NSInteger)delta {
     // information about synchronization's accuracy and delta
}

- (void)onPauseWithParticipantId:(NSString *)participantId {
    [_player pause];
}

- (void)onResumePlayWithParticipantId:(NSString *)participantId{
    [_player play];
}
```

{% endtab %}
{% endtabs %}

## Support

Need technical support? contact us at <Support@sceenic.co>.
