iOS
Documentation Update in Progress
We are currently revisiting and updating this section of our documentation to ensure it provides the most accurate and helpful information. Some content may be incomplete or outdated during this process.
Thank you for your patience! If you have any immediate questions, please don’t hesitate to contact our support team.
This guide shows how to embed a React.js web app in a WebView for iOS using SwiftUI. It also demonstrates how to enable messaging between the web app and the host app.
Setting Up the WebView
Use WKWebView
to embed the LiSA Player in an iOS application:
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
// Define the specific UIView subclass we are representing
typealias UIViewType = WKWebView
let urlString: String
func makeUIView(context: Context) -> WKWebView {
// Configuration
let webViewConfiguration = WKWebViewConfiguration()
// Allow video playback inline
webViewConfiguration.allowsInlineMediaPlayback = true
// Allow PiP for video
webViewConfiguration.allowsPictureInPictureMediaPlayback = true
// Allow JS to enter fullscreen
webViewConfiguration.preferences.isElementFullscreenEnabled = true
// Allow media to play without user gesture (use with caution, respect user settings)
webViewConfiguration.mediaTypesRequiringUserActionForPlayback = []
// JavaScript Injection
let scriptSource = """
window._lscLocalThemeOptions = { playerDismissCtaState: "enabled" };
"""
let userScript = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
let contentController = WKUserContentController()
contentController.addUserScript(userScript)
// Register the message handler with the coordinator
contentController.add(context.coordinator, name: "MessageFromLiSA")
webViewConfiguration.userContentController = contentController
// Create WKWebView
// Use .zero frame; SwiftUI will manage the actual frame size
let webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
// Only include this setting in Debug builds
#if DEBUG
if #available(iOS 16.4, *) {
// Explicitly allow inspection for Debug builds on iOS 16.4+
// Log confirmation
print("Setting webView.isInspectable = true")
// Set on the webView instance
webView.isInspectable = true
}
#endif
// Set background colors (optional, black might hide loading issues initially)
// Consider using .clear or removing these if the webpage has its own background
webView.backgroundColor = .black
webView.scrollView.backgroundColor = .black
// Can help if you want SwiftUI background to show through
webView.isOpaque = false
webView.scrollView.contentInsetAdjustmentBehavior = .never
// Set Delegates
webView.navigationDelegate = context.coordinator
// Needed for things like JavaScript alerts or window opening
webView.uiDelegate = context.coordinator
// Store reference in Coordinator
// Keep a reference if coordinator needs to access webView later
context.coordinator.webView = webView
// Initial Load
// Load the initial URL directly in makeUIView
if let url = URL(string: urlString) {
let request = URLRequest(url: url)
webView.load(request)
}
// Return the WKWebView directly
return webView
}
func updateUIView(_ webView: WKWebView, context: Context) {
// The `uiView` parameter *is* the WKWebView because we set UIViewType
// Check if the urlString prop has changed and reload if necessary
if let currentURL = webView.url?.absoluteString, currentURL == urlString {
// URL hasn't changed, do nothing
return
}
// URL string has changed, load the new one
if let url = URL(string: urlString) {
let request = URLRequest(url: url)
webView.load(request)
}
}
func makeCoordinator() -> Coordinator {
// Pass the WebView struct itself if needed
Coordinator(self)
}
// Coordinator
// Handles callbacks from the WKWebView
class Coordinator: NSObject, WKScriptMessageHandler, WKNavigationDelegate, WKUIDelegate {
// Reference back to the SwiftUI view
var parent: WebView
// Weak reference maybe better if lifecycle allows?
var webView: WKWebView?
init(_ parent: WebView) {
self.parent = parent
}
// WKScriptMessageHandler
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "MessageFromLiSA" {
// Handle message from JavaScript
print("Received message from LiSA: \(message.body)")
// You could trigger actions in your SwiftUI view here if needed,
// e.g., using @State variables passed down or Combine publishers.
}
}
// WKNavigationDelegate (Example Methods)
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("WebView did finish loading")
// You could update SwiftUI state here, e.g., hide a loading indicator
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print("WebView failed navigation: \(error.localizedDescription)")
// Handle loading errors
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
print("WebView failed provisional navigation: \(error.localizedDescription)")
// Handle initial loading errors (e.g., server not found)
}
// WKUIDelegate (Optional - Add methods as needed)
// Example: Handle JavaScript window.open()
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// If the request is a main frame navigation, open in Safari/default browser
if navigationAction.targetFrame == nil {
webView.load(navigationAction.request)
}
// Prevents opening a new webview window within the app
return nil
}
}
}
Using the WebView in SwiftUI
Here’s how to use the WebView
component:
struct ContentView: View {
// Example URL - Replace with your actual URL
private let urlString: String = "https://{clientId}.loveslisa.tech/s/{showId}"
var body: some View {
// Use edgesIgnoringSafeArea for older iOS/better compatibility
WebView(urlString: urlString)
.edgesIgnoringSafeArea(.all)
}
}
Last updated