iOS Integration
The iOS integration uses a WKWebView to render the Hubble WebView, enabling the integration of Hubble’s SDK into your iOS application. This document provides a step-by-step guide for integrating and using the Hubble WebView along with detailed descriptions of the primary functions.
Usage
- Setup the WebView
- Use WKWebViewto integrate Hubble’s WebView.
- Customize the WKWebViewconfiguration for message handling and navigation.
var webview: WKWebView!
override func loadView() {    let userContentController = WKUserContentController()    userContentController.add(self, name: "bridge") // web to native message handler
    let configuration = WKWebViewConfiguration()    configuration.userContentController = userContentController // Set content controller
    webview = WKWebView(frame: .zero, configuration: configuration)    webview.navigationDelegate = self    webview.uiDelegate = self    view = webview}- Initialization
- Initialize the HubbleWebViewControllerwith required parameters.
- Parameters
clientId: Client ID (provided by Hubble team).clientSecret: Client secret (provided by Hubble team).token: Token that uniquely identifies your user.env: Environment (devorprod).
init(clientId: String, clientSecret: String, token: String, env: String) {    self.clientId = clientId    self.clientSecret = clientSecret    self.token = token    self.env = env    super.init(nibName: nil, bundle: nil)}- Load the WebView
- Load the Hubble WebView with the proper URL.
- Customize navigation preferences.
override func viewDidLoad() {    let devUrl = URL(string: "https://vouchers.dev.myhubble.money/classic?clientId=\(clientId)&clientSecret=\(clientSecret)&token=\(token)")!    let url = URL(string: "https://vouchers.myhubble.money/classic?clientId=\(clientId)&clientSecret=\(clientSecret)&token=\(token)")!    webview.load(URLRequest(url: self.env == "dev" ? devUrl : url))    webview.allowsBackForwardNavigationGestures = true    webview.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true // Allow JavaScript pop-ups}- Handling Navigation
- Control navigation within the WebView.
- Redirect external links to the default browser.
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {    guard let url = navigationAction.request.url else {        decisionHandler(.allow)        return    }
   let baseUrl = URL(string: self.env == "dev" ? "https://vouchers.dev.myhubble.money" : "https://vouchers.myhubble.money")!   let paymentGatewayUrl = URL(string: "https://api.razorpay.com")!    if urlMatchesBaseUrl(url, baseUrl: baseUrl) {        decisionHandler(.allow) // Allow navigation within the web view    } else if urlMatchesBaseUrl(url, baseUrl: paymentGatewayUrl){        decisionHandler(.allow) // Allow navigation within the web view for paymentGateway    } else {        openURLExternally(url) // Open URL in external browser        decisionHandler(.cancel)    }}
private func urlMatchesBaseUrl(_ url: URL, baseUrl: URL) -> Bool {    // Check if the URL matches the base URL    return url.absoluteString.hasPrefix(baseUrl.absoluteString)}
private func openURLExternally(_ url: URL) {    // Open URL in the default browser    UIApplication.shared.open(url, options: [:], completionHandler: nil)}- Handling events
Add WKScriptMessageHandler to HubbleWebViewController
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    // check if message.body is close, pop view    if let message = message.body as? String, message == "close"{        // Handle close action        self.dismiss(animated: true)    }
    print(message.body) // here all the event passed from sdk will come, you can add your handler here    // ex. output {"event":"visit_voucher_edit_modal","properties":{"isModal":true}}}
override func loadView() {    let userContentController = WKUserContentController()    userContentController.add(self, name: "bridge")
    ...}This integration ensures seamless embedding of Hubble WebView into your iOS application while maintaining proper control over navigation and event handling. Below is the complete iOS snippet for better understanding
import UIKitimport WebKit
class HubbleWebViewController: UIViewController, WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler{
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {        print(message.body)    }
    private var clientId,clientSecret, token,env : String
    init(clientId: String, clientSecret: String, token: String, env: String) {        self.clientId = clientId        self.clientSecret = clientSecret        self.token = token        self.env = env        super.init(nibName: nil, bundle: nil)    }
    required init?(coder: NSCoder) {        fatalError("init(coder:) has not been implemented")    }
    var webview: WKWebView!
    override func loadView() {        let userContentController = WKUserContentController()        userContentController.add(self, name: "bridge")
        let configuration = WKWebViewConfiguration()        configuration.userContentController = userContentController
        webview = WKWebView(frame: .zero, configuration: configuration)        webview.navigationDelegate = self        webview.uiDelegate = self        view = webview        webview.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
    }
    override func viewDidLoad() {
        let url = URL(string: "https://vouchers.dev.myhubble.money/classic?clientId="+clientId+"&clientSecret="+clientSecret+"&token="+token)!
        webview.load(URLRequest(url: url))        webview.allowsBackForwardNavigationGestures = true        webview.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true
    }
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {        if let frame = navigationAction.targetFrame,           frame.isMainFrame {            return nil        }        webView.load(navigationAction.request)        return nil    }
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {        guard let url = navigationAction.request.url else {            decisionHandler(.allow)            return        }
        let baseUrl = URL(string: "https://vouchers.myhubble.money")! //update to vouchers.dev.myhubble.money for `dev` env        if urlMatchesBaseUrl(url, baseUrl: baseUrl) {            decisionHandler(.allow) // Allow navigation within the web view        } else {            openURLExternally(url) // Open URL in external browser            decisionHandler(.cancel)        }    }
    private func urlMatchesBaseUrl(_ url: URL, baseUrl: URL) -> Bool {        // Check if the URL matches the base URL        return url.absoluteString.hasPrefix(baseUrl.absoluteString)    }
    private func openURLExternally(_ url: URL) {        // Open URL in the default browser        UIApplication.shared.open(url, options: [:], completionHandler: nil)    }
} 
 