iOS Webview Setup
The GlamAR SDK allows real-time AR try-ons directly on iOS, enhancing the AR experience through live camera feed and image rendering. This guide will help you integrate the SDK into your iOS project using WebKit for web views and AVFoundation for media access.
Setup
Ensure your Xcode project imports the necessary frameworks:
Add these frameworks to your project by navigating to your project settings, selecting your target, and then the "General" tab. Under "Frameworks, Libraries, and Embedded Content," click the "+" button and add WebKit.framework and AVFoundation.framework.
WebView
Create a WebView using WebKit:
import UIKit
import WebKit
import AVFoundation
class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler {
var webView: WKWebView!
override func loadView() {
let prefs = WKWebpagePreferences()
prefs.allowsContentJavaScript = true
let config = WKWebViewConfiguration()
config.defaultWebpagePreferences = prefs
config.allowsInlineMediaPlayback = true
config.userContentController.add(self, name: "onLog") // This is the event handler that will listen to all the communication sent from SDK
config.mediaTypesRequiringUserActionForPlayback = []
webView = WKWebView(frame: .zero, configuration: config)
webView?.navigationDelegate = self
webView?.uiDelegate = self
}
}
We store the reference of webview as
webView
to use for communicating with the SDK.
Request Permissions
Ensure that you handle permissions appropriately, especially for camera access. Add the necessary privacy usage descriptions to your Info.plist
:
<key>NSCameraUsageDescription</key>
<string>This app requires access to the camera for virtual try-ons.</string>
Also, request camera permission inside the WebView using the AVFoundation library
private func checkCameraPermission() {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
self.loadWebPage()
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
if granted {
DispatchQueue.main.async {
self.loadWebPage()
}
} else {
DispatchQueue.main.async {
self?.handleCameraPermissionDenied()
}
}
}
case .denied, .restricted:
handleCameraPermissionDenied()
@unknown default:
handleCameraPermissionDenied()
}
}
private func loadWebPage() {
if let url = URL(string: "https://www.glamar.io/sdk") {
let request = URLRequest(url: url)
webView.load(request)
}
}
private func handleCameraPermissionDenied(){
print("Camera permission is required for this feature.")
// Don't open SDK , handle this on client side
}
If the user does not grant camera permission, do not open the SDK. Instead, handle it on the client side by providing clear instructions that camera permission is necessary for the SDK to function properly.
SDK
Once the WebView has loaded and camera access permission is granted, initialize the SDK by sending a JavaScript message
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// This method is called when the web view finishes loading
sendinit() // You can call your function here or perform other actions
}
private func sendinit() {
let type = "initialize"
let payload: [String: Any] = [
"type": type,
"payload": [
"apiKey": "YOUR_ACCESS_KEY",
"platform": "ios",
]
]
let jsonData = try? JSONSerialization.data(withJSONObject: payload)
if let jsonString = String(data: jsonData ?? Data(), encoding: .utf8) {
let script = "window.postMessage(\(jsonString), '*');"
webView.evaluateJavaScript(script, completionHandler: nil)
}
}
Replace 'YOUR_ACCESS_KEY' with your organization access key.
Event Listening
To listen to events from the SDK, implement a JavaScript message handler. This was added when we created our WebView
private func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let args = message.body as? String else { return }
do
{
let argsData = Data(args.utf8)
if let argsJson = try JSONSerialization.jsonObject(with: argsData, options: []) as? [String: Any],
let type = argsJson["type"] as? String {
handleJavaScriptMessage(type: type, argsJson: argsJson)
}
} catch {
print("Error processing JavaScript message: \(error)")
// Handle error appropriately, e.g., show an alert or log the error
// You can also implement specific error handling logic here
}
}
private func handleJavaScriptMessage(type: String, argsJson: [String: Any]) {
print("js type \(type) message \(argsJson)")
switch type {
case "loaded":
print("Page has loaded successfully")
case "sku-applied":
print("SKU applied")
}
}