How to integrate a WKWebView into an iOS SwiftUI project, configure the app to request camera and motion sensor permissions, and display the camera feed and motion data within the WebView.
Create a new SwiftUI project.
Create a new swift file, named WebView.swift
.
import Foundation
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let url: URL
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
let request = URLRequest(url: url)
webView.load(request)
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
}
}
ContentView.swift
.import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
WebView(url: URL(string: "<https://8th.io/iframe>")!)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Notice that we launch https://8th.io/iframe in the WebView.
This tool will allow you to confirm all necessary permissions are propagated to the app correctly. If we try to request motion and camera now, both requests fail. Let's start with the camera.
Configure the app to request motion sensors and camera.
Navigate to the Info tab of the target settings:
Click the + button on one of the line items and from the dropdown of the new App Category select "Privacy - Camera Usage Description". Provide a description of how the camera will be used as the value:
If we test the WebView again, we will find the camera permissions are requested, but the camera pipeline gets stuck on "has stream". We must configure the WebView to permit inline media playback to draw the stream to the canvas:
let webConfiguration = WKWebViewConfiguration()
webConfiguration.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
Now we can request camera permissions and draw the camera feed in our WebView! Let's move on to motion permissions. To request motion permissions, we need to set the uiDelegate on our WKWebViewMotion:
import Foundation
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
let url: URL
class Coordinator: NSObject, WKUIDelegate {
var parent: WebView
init(_ parent: WebView) {
self.parent = parent
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> WKWebView {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = context.coordinator
let request = URLRequest(url: url)
webView.load(request)
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {
}
}