如何在SwiftUI WKWebView中实现WKUIDelegate?

13

我正在使用Xcode v11创建一个Web应用程序,并且在实现WKUIDelegate以正确地在Web应用程序上显示JavaScript警报和确认时遇到了问题。

我有一个非常简单的Web视图应用程序,其中包含以下代码,但不确定如何正确地使用此代码实现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 Alert 和 Confirm?
1个回答

28

您需要使用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
    [...]
}

如果您想要符合WKNavigationDelegate,那么请遵循它并将navigationDelegate设置为context.coordinator

完整的代码在这里:

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()
    }
}

非常感谢您的回复!由于我以前没有真正使用过Swift,所以我不确定如何将您的代码实现到我的现有代码中。哈哈,我可以将我的代码添加到您的“Code goes here”注释中吗? - Skate to Eat
@Ohsik 我更新了答案,包括完整的代码和它所在的位置。 - fulvio
非常感谢。我已经添加了您的代码,但仍然不确定如何添加警报功能。我的警报和确认是由Javascript在Web应用程序上控制的。那么它将如何与Swift交互? - Skate to Eat
1
@Ohsik,我建议您接受这个作为您现有问题的正确答案,然后提出一个单独的问题,询问如何实现警报功能。 - fulvio
1
为该函数创建了一个新问题 https://dev59.com/37jna4cB1Zd3GeqP5Siw - Skate to Eat
太棒了!感谢您节省了我的时间;-) - ceyquem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接