如何将 WKUIDelegate 实现到 SwiftUI WKWebView 中?

How to implement WKUIDelegate into SwiftUI WKWebView?

我正在 Xcode v11 上创建网络应用程序,但在实施 WKUIDelegate 以在网络应用程序上正确显示 Javascript 警报和确认时遇到问题。

我在 ContentView.swift 上获得了一个非常简单的 webview 应用程序,其中包含以下代码,但不确定如何使用此代码正确实施 WKUIDelegate

import SwiftUI
import WebKit

struct Webview : UIViewRepresentable {
    let request: URLRequest
    var webview: WKWebView?

    init(web: WKWebView?, req: URLRequest) {
        self.webview = WKWebView()
        self.request = req
    }

    func makeUIView(context: Context) -> WKWebView  {
        return webview!
    }

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

    func goBack(){
        webview?.goBack()
    }

    func goForward(){
        webview?.goForward()
    }

    func reload(){
        webview?.reload()
    }
}

struct ContentView: View {

    let webview = Webview(web: nil, req: URLRequest(url: URL(string: "https://google.com")!))

    var body: some View {
        VStack {
            webview
            HStack() {
                Button(action: {
                    self.webview.goBack()
                }){
                    Image(systemName: "chevron.left")
                }.padding(32)

                Button(action: {
                    self.webview.reload()
                }){
                    Image(systemName: "arrow.clockwise")
                }.padding(32)

                Button(action: {
                    self.webview.goForward()
                }){
                    Image(systemName: "chevron.right")
                }.padding(32)
            }.frame(height: 32)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

在这段代码中实现 WKUIDelegate 的最佳方法是什么?因此,它将正确显示 Javascript 警报和确认。

你需要使用Coordinator然后符合WKUIDelegate:

class Coordinator: NSObject, WKUIDelegate {
    var parent: Webview

    init(_ parent: Webview) {
        self.parent = parent
    }

    // Delegate methods go here
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        // alert functionality goes here
    }
}

func makeCoordinator() -> Coordinator {
    Coordinator(self)
}

然后确保您的 updateUIView(..)uiDelegate 设置为 context.coordinator:

func updateUIView(_ uiView: WKWebView, context: Context) {
    uiView.uiDelegate = context.coordinator
    [...]
}

If you want to conform to WKNavigationDelegate then conform to it and set the navigationDelegate to the context.coordinator as well.

完整代码在这里:

import SwiftUI
import WebKit

struct Webview : UIViewRepresentable {
    let request: URLRequest
    var webview: WKWebView?

    init(web: WKWebView?, req: URLRequest) {
        self.webview = WKWebView()
        self.request = req
    }

    class Coordinator: NSObject, WKUIDelegate {
        var parent: Webview

        init(_ parent: Webview) {
            self.parent = parent
        }

        // Delegate methods go here

        func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
            // alert functionality goes here
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> WKWebView  {
        return webview!
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.uiDelegate = context.coordinator
        uiView.load(request)
    }

    func goBack(){
        webview?.goBack()
    }

    func goForward(){
        webview?.goForward()
    }

    func reload(){
        webview?.reload()
    }
}