【问题标题】:Argument Type does not conform to expected type 'WKScriptMessageHandler'参数类型不符合预期类型“WKScriptMessageHandler”
【发布时间】:2019-11-15 13:46:11
【问题描述】:

我正在尝试将 Swift 和 Javascript 与 SwiftUI 进行双向集成。
这是 WebKit 与 SwiftUI 的接口。

import SwiftUI
import WebKit

struct ggWebView : UIViewRepresentable {

    let filePath: String

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

    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.configuration.userContentController.add(self, name: "jsHandler")
        let bundleURL = Bundle.main.resourceURL!.absoluteURL
        let html = bundleURL.appendingPathComponent(filePath)
        uiView.loadFileURL(html, allowingReadAccessTo:bundleURL)
    }

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "jsHandler"{
            print(message.body)
        }
    }
}

userContentController.add(self, name: "jsHandler") 在self 和Argument type 'ggWebView' does not conform to expected type 'WKScriptMessageHandler' 处显示错误。

【问题讨论】:

    标签: swift wkwebview swiftui wkwebviewconfiguration


    【解决方案1】:

    由于WKScriptMessageHandler 要求实现它的对象从NSObject 继承,因此最好创建一个单独的类ContentController 来实现这些协议,而不是更改GgWebView 的类型。

    import SwiftUI
    import WebKit
    
    struct GgWebView: UIViewRepresentable {
    
        let filePath: String
        let contentController = ContentController()
    
        func makeUIView(context: Context) -> WKWebView  {
            return WKWebView()
        }
    
        func updateUIView(_ uiView: WKWebView, context: Context) {
            uiView.configuration.userContentController.add(contentController, name: "jsHandler")
            let bundleURL = Bundle.main.resourceURL!.absoluteURL
            let html = bundleURL.appendingPathComponent(filePath)
            uiView.loadFileURL(html, allowingReadAccessTo:bundleURL)
        }
    
        class ContentController: NSObject, WKScriptMessageHandler {
            func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
                if message.name == "jsHandler"{
                    print(message.body)
                }
            }
        }
    }
    

    您必须确认ggWebView(顺便说一句,这不是一个类的最佳名称,因为它应该以大写字母开头)到WKScriptMessageHandler 协议并实现func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) 方法。您必须将ggWebView 的类型从structure 更改为class。我可以看到你已经添加了一个userContentController(_:didReceive:) 方法,所以你只需要将你的类签名更新为:

    class ggWebView: UIViewRepresentable, WKScriptMessageHandler {
    

    【讨论】:

    • 遇到两个错误:Non-class type 'ggWebView' cannot conform to class protocol 'WKScriptMessageHandler 和 Non-class type 'ggWebView' cannot conform to class protocol 'NSObjectProtocol'
    • @Lonaso 尝试从 structure 更改为 class
    • 您还需要提供init,例如:init(filePath: String) { self.filePath = filePath }
    • 问题:如何从 contentController 实例中更改 GgWebView 的 @State 属性?
    • 只要使用 Maciej 的实现,就可以了
    猜你喜欢
    • 1970-01-01
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多