Hi,
How would I go about using the standard WebKit delegates in SwiftUI, such as:
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!)
{
activityView?.startAnimating()
self.title = "Loading...."
}
Here's what I have so far:
import SwiftUI
import UIKit
import Foundation
import WebKit
struct Support: View {
var body: some View {
NavigationView {
VStack {
WebView(request: URLRequest(url: URL(string: "https://www.connectingpeoplesoftware.com/iossupport")!))
}.navigationBarTitle(Text("Support"))
}
}
struct WebView: UIViewRepresentable
{
let request: URLRequest
func makeUIView(context: Context) -> WKWebView
{
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context)
{
uiView.load(request)
}
}
struct Support_Previews: PreviewProvider {
static var previews: some View {
Support()
}
}
}
Thanks in advance,
Dan
Your UIViewRepresentable has an associated class type called Coordinator which is used to set up these relationships. You need to implement makeCoordinator() in your WebView implementation to return an instance of your own class, and then set that class as the WKWebView's delegate.
Here's a quick example:
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
@Binding var title: String
var url: URL
var loadStatusChanged: ((Bool, Error?) -> Void)? = nil
func makeCoordinator() -> WebView.Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> WKWebView {
let view = WKWebView()
view.navigationDelegate = context.coordinator
view.load(URLRequest(url: url))
return view
}
func updateUIView(_ uiView: WKWebView, context: Context) {
// you can access environment via context.environment here
// Note that this method will be called A LOT
}
func onLoadStatusChanged(perform: ((Bool, Error?) -> Void)?) -> some View {
var copy = self
copy.loadStatusChanged = perform
return copy
}
class Coordinator: NSObject, WKNavigationDelegate {
let parent: WebView
init(_ parent: WebView) {
self.parent = parent
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
parent.loadStatusChanged?(true, nil)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
parent.title = webView.title ?? ""
parent.loadStatusChanged?(false, nil)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
parent.loadStatusChanged?(false, error)
}
}
}
struct Display: View {
@State var title: String = ""
@State var error: Error? = nil
var body: some View {
NavigationView {
WebView(title: $title, url: URL(string: "https://www.apple.com/")!)
.onLoadStatusChanged { loading, error in
if loading {
print("Loading started")
self.title = "Loading…"
}
else {
print("Done loading.")
if let error = error {
self.error = error
if self.title.isEmpty {
self.title = "Error"
}
}
else if self.title.isEmpty {
self.title = "Some Place"
}
}
}
.navigationBarTitle(title)
}
}
}
struct WebView_Previews: PreviewProvider {
static var previews: some View {
Display()
}
}