# Add chat capability to the Contact Center SDK for iOS

<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

Add the chat service one of two ways: the [standard chat service](#add-standard-chat-service), or [Zoom Virtual Agent chat](#add-virtual-agent-chat-service).

## Add standard chat service

Follow these steps to add standard chat functionality.

### Initialize the standard chat service

Create an instance of class `ZoomCCItem` to set the channel to use, chat or video. For chat, set the `sdkType` property to `ZoomCCIInterfaceType_Chat`.

Include the `entryId` from your Zoom Contact Center flow.

```objectivec
ZoomCCItem *item = [ZoomCCItem new];
item.sdkType = ZoomCCIInterfaceType_Chat;
item.entryId = APP_CHAT_ENTRY_ID;
```

```swift
let item = ZoomCCItem.init()
item.sdkType = .chat
item.entryId = APP_CHAT_ENTRY_ID
```

### Pass engagement variables (optional)

To pass custom application context variables to a chat engagement, configure custom variables in Contact Center Management and set its value source to **Application**. Before calling `initializeWithItem`, use the variable name as the key and the application-provided value as the dictionary value in `ZoomCCItem.engagementVariables`.

> **Missing variables**
>
> Missing variables do not block the engagement flow, but nodes that depend on them may not work as expected.

```objectivec
ZoomCCItem *item = [ZoomCCItem new];
item.sdkType = ZoomCCIInterfaceType_Chat;
item.entryId = APP_CHAT_ENTRY_ID;
item.engagementVariables = @{@"test_key":@"test_value"};
```

```swift
let item = ZoomCCItem.init()
item.sdkType = .chat
item.entryId = APP_CHAT_ENTRY_ID
item.engagementVariables = ["test_key": "test_value"]
```

### Fetch the standard chat service instance

Fetch the chat service instance and set its delegate to receive callbacks from `ZoomCCSDK`. When the status of the service is `ZoomCCSDKStatus_Initial`, initialize the chat service by calling `initializeWithItem:` and `login`. The service then connects to the Contact Center server to fetch information, and you can send and receive messages to and from the server.

```objectivec
id<ZoomCCChatService> chatService = [[ZoomCCInterface sharedInstance] chatService];
chatService.chatDelegate = self;
if (chatService.status == ZoomCCSDKStatus_Initial) {
    [chatService initializeWithItem:item];
    [chatService login];
}
```

```swift
let chatService = ZoomCCInterface.sharedInstance().chatService()
chatService.chatDelegate = self
if (chatService.status == .initial) {
    chatService.initialize(with: item)
    chatService.login()
}
```

### Show the standard chat view

To show the chat view, call the function below. The call back gets the view's instance and displays it.

```objectivec
__weak typeof(self) wself = self;
[chatService fetchUI:^(UIViewController * _Nonnull viewController) {
    [wself directShow:viewController];
}];
```

```swift
chatService .fetchUI { vc in
    self.navigationController?.pushViewController(vc, animated: true)
}
```

## Forcibly end an active chat engagement

To forcibly end a chat engagement, call the `endChat` method. This closes the chat view presented by the SDK and returns control to your application. Any service instances created by the Contact Center SDK for this chat are released.

```objectivec
id<ZooomCCChatService> chatService = [[ZoomCCInterface sharedInstance] chatService];
[chatService endChat];
```

```swift
let chatService = ZoomCCInterface.sharedInstance().chatService()
chatService.endChat()
```

## Add Virtual Agent chat service

Follow these steps to add Virtual Agent chat functionality.

### Initialize the Virtual Agent chat service

Create an instance of the `ZoomCCItem` class to set the Virtual Agent channel to use, chat or video. For Virtual Agent chat, set the `sdkType`` property to `ZoomCCIInterfaceType_ZVA`.

Include the `entryId` from your Virtual Agents flow.

```objectivec
ZoomCCItem *item = [ZoomCCItem new];
item.sdkType = ZoomCCIInterfaceType_ZVA;
item.entryId = APP_ZVA_ENTRY_ID;
```

```swift
let item = ZoomCCItem.init()
item.sdkType = .ZVA
item.entryId = APP_ZVA_ENTRY_ID
```

### Pass engagement variables (optional)

To pass custom application context variables to a Virtual Agent engagement, configure custom variables in Contact Center Management and set its value source to **Application**. Before calling `initializeWithItem`, use the variable name as the key and the application-provided value as the dictionary value in `ZoomCCItem.engagementVariables`.

> **Missing variables**
>
> Missing variables do not block the engagement flow, but nodes that depend on them may not work as expected.

```objectivec
ZoomCCItem *item = [ZoomCCItem new];
item.sdkType = ZoomCCIInterfaceType_ZVA;
item.entryId = APP_ZVA_ENTRY_ID;
item.engagementVariables = @{@"test_key":@"test_value"};
```

```swift
let item = ZoomCCItem.init()
item.sdkType = .ZVA
item.entryId = APP_ZVA_ENTRY_ID
item.engagementVariables = ["test_key": "test_value"]
```

### Fetch the Virtual Agent chat service instance

Fetch the Virtual Agent chat service instance and set its delegate to receive callbacks from `ZoomCCSDK`. When the service's status is `ZoomCCSDKStatus_Initial`, initialize the chat service by calling `initializeWithItem:` and `login`. The service then connects to the Contact Center server to fetch information.

```objectivec
id<ZoomCCChatService> zvaService = [[ZoomCCInterface sharedInstance] zvaService];
zvaService.chatDelegate = self;
if (zvaService.status == ZoomCCSDKStatus_Initial) {
  [zvaService initializeWithItem:item];
  [zvaService login];
}
```

```swift
let zvaService = ZoomCCInterface.sharedInstance().zvaService()
zvaService.chatDelegate = self
if (zvaService.status == .initial) {
  zvaService.initialize(with: item)
  zvaService.login()
}
```

### Show the Virtual Agent chat view

To show the Virtual Agent chat view, call this function. The callback gets and displays the view's instance.

```objectivec
__weak typeof(self) wself = self;
[zvaService fetchUI:^(UIViewController * _Nonnull viewController) {
    [wself directShow:viewController];
}];
```

```swift
zvaService.fetchUI { vc in
    if (vc != nil) {
        self.navigationController?.pushViewController(vc!, animated: true)
    }
}
```

## Forcibly end an active Virtual Agent engagement

To forcibly end a Virtual Agent engagement, call the endChat method. This closes the chat view presented by the SDK and returns control to your application. Any service instances created by the Contact Center SDK for this chat are released.

```objectivec
id<ZooomCCChatService> zvaService = [[ZoomCCInterface sharedInstance] zvaService];
[zvaService endChat];
```

```swift
let zvaService = ZoomCCInterface.sharedInstance().zvaService()
zvaService.endChat()
```

## Embed chat in iOS apps

To use the Contact Center for web in iOS apps, create a `WKUserScript` to pass the current environment data. Then transmit a callback. Finally, create a `WKWebView` and load the `WebSDK` URL generated in the campaign management page.

### Transmit the current environment data

Create a `WKUserScript` to transmit the current environment data.

```objectivec

WKUserContentController *userContentController = [[WKUserContentController alloc] init];
NSString * injectScriptStr = @"window.zoomCampaignSdkConfig = window.zoomCampaignSdkConfig || { "
"language : 'user language',"
"firstName: 'user first name',"
"lastName: 'user first name',"
"nickName: 'user nickname',"
"address: 'user address',"
"company: 'user company',"
"email : 'user email',"
"phoneNumber : 'user phone number'};";

WKUserScript *injectScript = [[WKUserScript alloc] initWithSource:injectScriptStr injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:true];
[userContentController addUserScript:injectScript];

```

```swift
let userContentController = WKUserContentController()
let webviewcConfig = WKWebViewConfiguration()
webviewcConfig.userContentController = userContentController

//pass the parameters to webview
let injectScriptStr =
"""
    window.zoomCampaignSdkConfig = window.zoomCampaignSdkConfig || {
        language: 'user language',
        firstName: 'user first name',
        lastName: 'user last name',
        nickName: 'user nick name',
        address: 'user address',
        company: 'user company',
        email: 'user email',
        phoneNumber: 'user phonenumber'
    };
"""

let injectScript = WKUserScript(source: injectScriptStr, injectionTime: .atDocumentStart, forMainFrameOnly: true)
userContentController.addUserScript(injectScript)
```

For the key `language` in the transmit data, use one of these supported languages:

```plaintext
"en-US"
"da-DK"
"de-DE"
"en-AU"
"en-GB"
"en-NZ"
"es-ES"
"es-MX"
"es-US"
"fr-CA"
"fr-FR"
"id-ID"
"it-IT"
"ja-JP"
"ko-KR"
"nl-NL"
"pl-PL"
"pt-BR"
"pt-PT"
"ro-RO"
"ru-RU"
"sv-SE"
"tr-TR"
"vi-VN"
"zh-CN"
"zh-TW"
"ar-AE"
"ar-SA"
"ca-ES"
"cs-CZ"
"fi-FI"
"he-IL"
"hi-IN"
"ka-GE"
"ms-MY"
"nb-NO"
"th-TH"
```

### Transmit a callback

Create a `WKUserScript` to transmit a callback function into the Javascript context. Use this callback function when the `WebSDK` needs to terminate the current session and return to the previous `viewController`.

```objectivec
NSString *exitHandlerScriptStr =
    @"window.addEventListener('zoomCampaignSdk:ready', () => {"
      "if (window.zoomCampaignSdk) { "
        "window.zoomCampaignSdk.native = {"
          "exitHandler: {"
            "handle: function() {"
              "window.webkit.messageHandlers.zoomLiveSDKMessageHandler.postMessage('close_web_vc');"
            "}"
          "}"
        "};"
      "}"
    "});";

    WKUserScript *exitScript = [[WKUserScript alloc] initWithSource:exitHandlerScriptStr injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:true];
    [userContentController addUserScript:exitScript];
    [userContentController addScriptMessageHandler:self name:@"zoomLiveSDKMessageHandler"];
```

```swift
//pass the exit webview handler callback to webview
let exitHandlerScriptStr =
"""
    window.addEventListener('zoomCampaignSdk:ready', () => {
          if (window.zoomCampaignSdk) {
              window.zoomCampaignSdk.native = {
                  exitHandler: {
                      handle: function() {
                          window.webkit.messageHandlers.zoomLiveSDKMessageHandler.postMessage('close_web_vc');
                    }
                  }
              };
          }
    });
"""

let exitScript = WKUserScript(source: exitHandlerScriptStr, injectionTime: .atDocumentStart, forMainFrameOnly: true)
userContentController.addUserScript(exitScript)

//register self as the javascript message handler named "zoomLiveSDKMessageHandler"
userContentController.add(self, name: "zoomLiveSDKMessageHandler")
```

In the previous code sample, the instance `self` is UIViewController or another kind of instance. It should conform to the protocol `WKScriptMessageHandler` and have the method shown in this next code sample.

```objectivec
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    if ([message.name isEqualToString:@"zoomLiveSDKMessageHandler"]) {
        if ([message.body isEqualToString:@"close_web_vc"]) {
            //todo handle current webview controller's pop action, like
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
}
```

```swift
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if message.name == "zoomLiveSDKMessageHandler", let bodyString = message.body as? String {
        if bodyString == "close_web_vc" {
          // Handle current webview controller's pop action, like
          navigationController?.popViewController(animated: true)
        }
    }
}
```

When the WebSDK needs to close the current `viewcontroller`, call this Javascript method.

```javascript
window.zoomCampaignSdk.native.exitHandler.handle();
```

Since we had a message handler registered named `zoomLiveSDKMessageHandler`, then this
next method would be called within a message. In the callback, add logic to leave
the current webview.

```objectivec
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
```

```swift
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
```

### Create a `WKWebView` and load the WebSDK URL

```objectivec
//the instance webviewcConfig is created by step 1.
webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:webviewcConfig];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[self.view addSubview:webView];

NSURL *url = [NSURL URLWithString:@"Zoom contact center target url"];
if (url) {
    [webView loadRequest:[NSURLRequest requestWithURL:url]];
}
```

```swift
//the instance webviewcConfig is created by step 1.
webView = WKWebView(frame: view.bounds, configuration: webviewcConfig)
webView.uiDelegate = self
webView.navigationDelegate = self
view.addSubview(webView)
if let url = URL(string: "Zoom contact center target url")
{
      webView.load(URLRequest(url: url))
}
```

For native mobile applications using Swift or Objective-C, adapt to the user's language preferences in two ways.

1. For iOS 16 and above, use the device's regional language setting.

    ```objectivec
    NSString *currentLanguage = [[NSLocale currentLocale] languageCode];
    ```

    ```swift
    let currentLanguage = Locale.current.language.languageCode?.identifier ?? "en"
    ```

2. Respect the user's preferred languages set on their device.

    ```objectivec
    NSArray *preferredLanguages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"];
    ```

    ```swift
    let preferredLanguages = UserDefaults.standard.object(forKey: "AppleLanguages") as? [String]
    ```

## Callbacks

These callbacks are available for both chat and video.

-   [`onEngagementVariablesRequired`](#onengagementvariablesrequired)
-   [`error`](#error)
-   [`engagementStart`](#engagementstart)
-   [`engagementEnd`](#engagementend)
-   [`eventChange`](#eventchange)
-   [`loginStatusChanged`](#loginstatuschanged)
-   [`unreadMsgCountChanged` (chat only)](#unreadmsgcountchanged-chat-only)

### `onEngagementVariablesRequired`

Called after login when the engagement application variables are known. Each dictionary can contain `variableGroupName`, `variableName`, and `attributeName`. Use `attributeName` as the key in `ZoomCCItem.engagementVariables`.

This callback only reports the variable definitions; the SDK sends matching values when the engagement is created.

-   `service`: the current service.
-   `variables`: an array of dictionaries describing variables that the current engagement may require. Each dictionary can contain `variableGroupName`, `variableName`, or `attributeName`.

    ```objectivec
    - (void)onService:(id<ZoomCCService>)service
    engagementVariablesRequired:(NSArray<NSDictionary<NSString *, NSString *> *> *)variables;
    ```

    ```swift
    func onService(_ service: ZoomCCService, engagementVariablesRequired variables: [[String: String]]) {
    }
    ```

### `error`

Sent after a service error.

-   `service` &mdash; the current service.
-   `error` &mdash; the service error code. See [errors](contact-center/errors) for details.
-   `detail` &mdash; the error details.

    ```objectivec
    - (void)onService:(id<ZoomCCService>)service error:(NSUInteger)error  detail:(NSInteger)detail;
    ```

    ```swift
    func onService(_ service: ZoomCCService, error: UInt, detail: Int) {
    }
    ```

### `engagementStart`

Sent after the service creates an engagement.

-   `service` &mdash; the current service.
-   `engagementId` &mdash; the engagement identifier.

    ```objectivec
    - (void)onService:(id<ZoomCCService>)service engagementStart:(NSString*)engagementId;
    ```

    ```swift
    func onService(_ service: ZoomCCService, engagementStart engagementId: String) {
    }
    ```

### `engagementEnd`

Sent after the engagement ends.

-   `service` &mdash; the current service.
-   `engagementId` &mdash; the engagement identifier.

    ```objectivec
    - (void)onService:(id<ZoomCCService>)service engagementEnd:(NSString*)engagementId;
    ```

    ```swift
    func onService(_ service: ZoomCCService, engagementEnd engagementId: String) {
    }
    ```

### `eventChange`

Sent when a change has occurred, for example, due to a user action.

-   `service` &mdash; the current service.
-   `event` &mdash; the event that occurred.

    ```objectivec
    - (void)onService:(id<ZoomCCService>)service eventChange:(ZoomCCSDKEvent)event;
    ```

    ```swift
    func onService(_ service: ZoomCCService, eventChange event: ZoomCCSDKEvent) {
    }
    ```

### `loginStatusChanged`

Sent when the login status has changed.

-   `service` &mdash; the current service.
-   `status` &mdash; the service status. `ZoomCCSDKStatus_Login` means the logging succeeded.

    ```objectivec
    - (void)onService:(id<ZoomCCService>)service loginStatusChanged:(ZoomCCSDKStatus)status;
    ```

    ```swift
    func onService(_ service: ZoomCCService, loginStatusChanged status: ZoomCCSDKStatus) {
    }
    ```

### `unreadMsgCountChanged` (chat only)

Sent when the number of unread messages has changed. Only sent for chat.

-   `service` &mdash; the current service.
-   `status` &mdash; the service status. `ZoomCCSDKStatus_Login` means the logging succeeded.

    ```objectivec
    - (void)onChatService:(id<ZoomCCChatService>)service unreadMsgCountChanged:(NSUInteger)count;
    ```

    ```swift
    func onChatService(_ service: ZoomCCChatService, unreadMsgCountChanged count: UInt) {
    }
    ```
