Skip to content

Integrating LIQA into iOS app

Below is the guide for LIQA integrating LIQA into an iOS app using Swift language.

WebView with LIQA integrated

Here is a ready-to-use implementation of WebView with integrated LIQA functionality.

Production recommendation

For the simplicity of the guide, WebView loads the HTML page from a string containing the page‘s HTML content.

In a real-world application, you may consider loading the page from a CDN managed by your organization. Check the Hosting the HTML Page section for more details.

IMPORTANT

WebView should be opened over HTTPS. Without HTTPS, the camera access will not be requested, and the camera cannot be used.

When hosting locally, you can open the WebView using https://localhost/ as the baseUrl

swift
webView.loadHTMLString(HTML, baseURL: URL(string: "https://localhost/"))
webView.loadHTMLString(HTML, baseURL: URL(string: "https://localhost/"))
swift
import SwiftUI
import WebKit

let HTML = """ PUT THE HTML PAGE CONTENT HERE """

struct LiqaWebView: UIViewRepresentable {
  private let onLiqaEvent: (String, [String: Any]?) -> Void

  init(onLiqaEvent: @escaping (String, [String: Any]?) -> Void) {
    self.onLiqaEvent = onLiqaEvent
  }

  func makeUIView(context: Context) -> WKWebView {
    let configuration = WKWebViewConfiguration()
    configuration.allowsInlineMediaPlayback = true

    let controller = WKUserContentController()
    // Communication interface between WebView‘s JavaScript and the Native App
    controller.add(context.coordinator, name: "NativeApp")
    configuration.userContentController = controller

    let webView = WKWebView(frame: .zero, configuration: configuration)
    webView.navigationDelegate = context.coordinator
    // `https://` is required to get WebView camera working
    webView.loadHTMLString(HTML, baseURL: URL(string: "https://YOUR.DOMAIN.COM"))

    return webView
  }

  func updateUIView(_ uiView: WKWebView, context: Context) {}

  func makeCoordinator() -> Coordinator {
    Coordinator(onPostMessage: handlePostMessage)
  }

  private func handlePostMessage(message: String) {
    guard let data = message.data(using: .utf8),
      let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
      let name = json["name"] as? String
    else {
      return
    }
      
    let payload = json["payload"] as? [String: Any]
      
    onLiqaEvent(name, payload)
  }

  class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
    private let onPostMessage: (String) -> Void

    init(onPostMessage: @escaping (String) -> Void) {
      self.onPostMessage = onPostMessage
    }

    func userContentController(
      _ userContentController: WKUserContentController, didReceive message: WKScriptMessage
    ) {
      if let body = message.body as? String {
        onPostMessage(body)
      }
    }
  }
}
import SwiftUI
import WebKit

let HTML = """ PUT THE HTML PAGE CONTENT HERE """

struct LiqaWebView: UIViewRepresentable {
  private let onLiqaEvent: (String, [String: Any]?) -> Void

  init(onLiqaEvent: @escaping (String, [String: Any]?) -> Void) {
    self.onLiqaEvent = onLiqaEvent
  }

  func makeUIView(context: Context) -> WKWebView {
    let configuration = WKWebViewConfiguration()
    configuration.allowsInlineMediaPlayback = true

    let controller = WKUserContentController()
    // Communication interface between WebView‘s JavaScript and the Native App
    controller.add(context.coordinator, name: "NativeApp")
    configuration.userContentController = controller

    let webView = WKWebView(frame: .zero, configuration: configuration)
    webView.navigationDelegate = context.coordinator
    // `https://` is required to get WebView camera working
    webView.loadHTMLString(HTML, baseURL: URL(string: "https://YOUR.DOMAIN.COM"))

    return webView
  }

  func updateUIView(_ uiView: WKWebView, context: Context) {}

  func makeCoordinator() -> Coordinator {
    Coordinator(onPostMessage: handlePostMessage)
  }

  private func handlePostMessage(message: String) {
    guard let data = message.data(using: .utf8),
      let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
      let name = json["name"] as? String
    else {
      return
    }
      
    let payload = json["payload"] as? [String: Any]
      
    onLiqaEvent(name, payload)
  }

  class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
    private let onPostMessage: (String) -> Void

    init(onPostMessage: @escaping (String) -> Void) {
      self.onPostMessage = onPostMessage
    }

    func userContentController(
      _ userContentController: WKUserContentController, didReceive message: WKScriptMessage
    ) {
      if let body = message.body as? String {
        onPostMessage(body)
      }
    }
  }
}

Before integrating the snippet into your app, please, ensure that:

Application integration example

Here is an app‘s entry point, showcasing a sample integration of LiqaWebView:

swift
import SwiftUI
import Toast

@main
struct ExampleApp: App {
  var body: some Scene {
    WindowGroup {
      LiqaWebView(onLiqaEvent: handleLiqaEvent)
    }
  }

  // The App‘s business logic for handling LIQA events
  private func handleLiqaEvent(name: String, payload: [String: Any]?) {
    var text = "LIQA: \(name)"

    if let payload = payload {
      var extras = "\(payload)"
      // Do not overwhelm the log
      if extras.count >= 1024 {
        extras = String(extras.prefix(1024)) + "..."
      }
      text += "\n\(extras)"
    }

    log(text: text)
  }

  private func log(text: String) {
    guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
      let window = scene.windows.first,
      let controller = window.rootViewController else {
        return
      }
      
      controller.view.makeToast(text)
  }
}
import SwiftUI
import Toast

@main
struct ExampleApp: App {
  var body: some Scene {
    WindowGroup {
      LiqaWebView(onLiqaEvent: handleLiqaEvent)
    }
  }

  // The App‘s business logic for handling LIQA events
  private func handleLiqaEvent(name: String, payload: [String: Any]?) {
    var text = "LIQA: \(name)"

    if let payload = payload {
      var extras = "\(payload)"
      // Do not overwhelm the log
      if extras.count >= 1024 {
        extras = String(extras.prefix(1024)) + "..."
      }
      text += "\n\(extras)"
    }

    log(text: text)
  }

  private func log(text: String) {
    guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
      let window = scene.windows.first,
      let controller = window.rootViewController else {
        return
      }
      
      controller.view.makeToast(text)
  }
}

Feel free to adapt the example for your‘s application needs.

Application permissions configuration

For LiqaWebView to function correctly, you‘ll have to configure camera permissions in your Xcode project:

Include Privacy - Camera Usage Description is in the Info > Custom iOS Target Properties.

For further assistance, refer to the Apple‘s documentation on Requesting authorization to capture and save media.

Need Assistance?

If you have any questions regarding the integration or need further assistance, please contact Haut.AI Support Team with this request via the Support Desk.