# iOS integration scenarios Here are a couple of scenarios you might encounter when you integrate the sample iOS app. ## Scenario 1: Embed custom website in web view Embedded a customer's website in the iOS web view. The site contains links that use the ZVA WebSDK, such as the example on [Zoom's website](https://zoom.us/). You don't need to generate the full-page chat URL. However, in **Targeting**, you should check **Mobile**. ![](/img/zva-targeting.png) ## Scenario 2: Trigger web view from native button Users trigger native events in the iOS app, such as click a button to open the web view that displays the web chat window. ### Case 1: Close web chat view When the user chooses the close button to end the web chat, it: - Handles the callback event in `WebViewController`. - Closes the current native web view window. - Initializes the web view controller by passing in the URL when the user clicks the button. Here is an example in Objective-C. ```objectivec - (void)openCampaignChatDemoPage_closeChat:(NSString *)url { ZMWebviewConfiguration *config = [[ZMWebviewConfiguration alloc] init]; ZMLiveSDKWebviewController *vc = [[ZMLiveSDKWebviewController alloc] initWithURL:url webviewConfiguration:config]; [self.navigationController pushViewController:vc animated:YES]; } ``` In the `userContentController:didReceiveScriptMessage: method`, add message handling logic to close the current web view. Here is an example in Objective-C. ```objectivec - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([message.name isEqualToString:kZMCCMessageHandlerName_Exit]) { if ([message.body isEqualToString:kZCMCCMessage_ExitCmdValue]) { // Handle current webview controller's pop action [self removeWebViewMessageHandlers]; dispatch_async(dispatch_get_main_queue(), ^{ [self.navigationController popViewControllerAnimated:YES]; }); } } } ``` ### Case 2: Pass native parameters to web chat Users choose the button to open a chat in a web view and bring some parameters into the web context. Here is an example in Objective-C. ```objectivec - (void)openCampaignChatDemoPage_bringParamsToWebChat:(NSString *)url { ZMWebviewConfiguration *config = [[ZMWebviewConfiguration alloc] init]; ZMLiveSDKWebviewController *vc = [[ZMLiveSDKWebviewController alloc] initWithURL:url webviewConfiguration:config]; [self.navigationController pushViewController:vc animated:YES]; } ``` Use the injected JavaScript string to format the parameters you need to pass in the .js context. ### Case 3: Open URL in the current web view (In-App) An example of this case is when the web view opens another URL from within. Normally, when users click a link in the web page, it opens the URL inside the web view. The `WKWebview` provides the `webView:decidePolicyForNavigationAction:decisionHandler:` callback to handle the case. Here is an example in Objective-C. ```objectivec - (void)openCampaignChatDemoPage_openLinkInWebView:(NSString *)url { ZMWebviewConfiguration *config = [[ZMWebviewConfiguration alloc] init]; ZMLiveSDKWebviewController *vc = [[ZMLiveSDKWebviewController alloc] initWithURL:url webviewConfiguration:config]; [self.navigationController pushViewController:vc animated:YES]; } ``` In the `webView:decidePolicyForNavigationAction:decisionHandler: method`, if you want to handle the navigation action in the current web view, you should pass `WKNavigationActionPolicyAllow` to the `decisionHandler`. You can also handle it yourself and pass the `WKNavigationActionPolicyCancel` to the `decisionHandler`. Here is an example in Objective-C. ```objectivec - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler { //The download action only supports iOS 14.5+ version. if (@available(iOS 14.5, *)) { if (navigationAction.shouldPerformDownload) { decisionHandler(WKNavigationActionPolicyDownload); return; } } // For specific URLS, like the URL with scheme "tel", as the WKWebview has no default process logic, here we need to handle it ourselves. We should judge the scheme is not "https" and not "http" firstly, then use system method to handle URL. NSString *urlScheme = [navigationAction.request.URL.scheme lowercaseString]; if (urlScheme.length && (![urlScheme isEqualToString:@"https"] && ![urlScheme isEqualToString:@"http"]) && [[UIApplication sharedApplication] canOpenURL:navigationAction.request.URL]) { NSDictionary *options = @{UIApplicationOpenURLOptionUniversalLinksOnly:@NO}; [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:options completionHandler:nil]; decisionHandler(WKNavigationActionPolicyCancel); return; } // Developers can chose to process the navigation by the url. For example, if the url is https://zoom.us, developers can choose to open it in Safari or just call the block "decisionHandler(WKNavigationActionPolicyAllow)" to handle it in the current WkWebview. That's depend on the the developers requests. if (navigationAction.navigationType == WKNavigationTypeLinkActivated) { NSDictionary *options = @{UIApplicationOpenURLOptionUniversalLinksOnly:@NO}; if (navigationAction.targetFrame) { if (navigationAction.targetFrame.isMainFrame) { decisionHandler(WKNavigationActionPolicyAllow); } else { [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:options completionHandler: nil]; decisionHandler(WKNavigationActionPolicyCancel); } } else { [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:options completionHandler: nil]; decisionHandler(WKNavigationActionPolicyCancel); } } else { decisionHandler(YES); } } ``` ### Case 4: Open URL in system browser In the iOS app, open the URL of the button of the chat window in the system browser. When using DOM elements like `Open in New Tab` to open a new URL, the `webView:decidePolicyForNavigationAction:decisionHandler:` invokes the callback method. See the sample code implementation for handling this scenario. If you use `window.open()` in the JavaScript context and do not implement the `webView:decidePolicyForNavigationAction:decisionHandler:` callback method, then the `webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:` method runs. See the sample code implementation for this case. Here is an example in Objective-C. ```objectivec - (void)openCampaignChatDemoPage_openLinkInBrowser:(NSString *)url { ZMWebviewConfiguration *config = [[ZMWebviewConfiguration alloc] init]; ZMLiveSDKWebviewController *vc = [[ZMLiveSDKWebviewController alloc] initWithURL:url webviewConfiguration:config]; vc.openURLInSystemBrowser = YES; [self.navigationController pushViewController:vc animated:YES]; } ``` Use the `userContentController:didReceiveScriptMessage: method` to process the information passed from the web. Here is an example in Objective-C. ```objectivec - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([message.name isEqualToString:kZMCCMessageHandlerName_Exit]) { if ([message.body isEqualToString:kZCMCCMessage_ExitCmdValue]) { [self removeWebViewMessageHandlers]; dispatch_async(dispatch_get_main_queue(), ^{ [self.navigationController popViewControllerAnimated:YES]; }); } } else if ([message.name isEqualToString:kZMCCMessageHandlerName_CommonHandler]) { // Handle the openURL cmd. Developers should open a new UIViewController to load the url within the value, or to open the url in safari. if (((NSString *)message.body).length) { NSDictionary *dic = nil; NSString *messageBody = message.body; @try { dic = [NSJSONSerialization JSONObjectWithData:[messageBody dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; } @catch (NSException *exception) { } @finally { } } } else if ([message.name isEqualToString:kZMCCMessageHandlerName_SuportHandOff]) { // Handle the support_handoff cmd. For this event, the javascript context will archive all the messages into a json string, and the post the json string to native logic by the message.body. Here developer should handle the json string as needed. NSLog(@"%@", message.body); if (self.showDialogOfSupportHandoff) { UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Support handoff message body" message:message.body preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; [self.navigationController presentViewController:alert animated:YES completion:nil]; } } } ``` ### Case 5: Open URL in SFSafariViewController (In-App) Use the internal browser, such as `SFSafariViewController`, to open the ZVA Web SDK URL in the iOS app. The method to trigger the opening of the URL is the same as in Case 4. Here is an example in Objective-C. ```objectivec - (void)openCampaignChatDemoPage_openLinkInSeperateViewController:(NSString *)url { ZMWebviewConfiguration *config = [[ZMWebviewConfiguration alloc] init]; ZMLiveSDKWebviewController *vc = [[ZMLiveSDKWebviewController alloc] initWithURL:url webviewConfiguration:config]; vc.openURLInSystemBrowser = NO; [self.navigationController pushViewController:vc animated:YES]; } ``` Use the `userContentController:didReceiveScriptMessage: method` to handle similar information passed from the web. For an example, see Case 4. ### Case 6: Dispatch support handoff event Use JavaScript's handoff event to pass data from the web to the iOS native app. Here is an example in Objective-C. ```objectivec - (void)openCampaignChatDemoPage_supportHandOffEvent:(NSString *)url { ZMWebviewConfiguration *config = [[ZMWebviewConfiguration alloc] init]; ZMLiveSDKWebviewController *vc = [[ZMLiveSDKWebviewController alloc] initWithURL:url webviewConfiguration:config]; vc.showDialogOfSupportHandoff = YES; [self.navigationController pushViewController:vc animated:YES]; } ``` You can handle the handoff callback event in the `userContentController:didReceiveScriptMessage: method`. Here is an example in Objective-C. ```objectivec - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([message.name isEqualToString:kZMCCMessageHandlerName_SuportHandOff]) { // Handle the support_handoff cmd. For this event, the javascript context will archive all the messages into a json string, and the post the json string to native logic by the message.body. Here developer should handle the json string as needed. NSLog(@"%@", message.body); if (self.showDialogOfSupportHandoff) { UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Support handoff message body" message:message.body preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; [self.navigationController presentViewController:alert animated:YES completion:nil]; } } } ```