Swift 项目 Javascript 双向通信

Swift project with Javascript two way communication

我正在构建一个 iOS Swift 应用程序,我想与 javascript 进行双向通信。我需要从 javascript 收听消息 (json) 并发送 json。 我知道有很多帖子解决了这个问题,但我无法解决这个问题,因为我是 iOS 开发的新手。

根据我在其他回复中看到的 and/or 其他教程页面,例如 medium,为了做到这一点,他们构建了一个 class 来实现 UIViewController 协议。但是我的视图是一个实现协议视图的结构。从我的角度来看,如何使用协议 UIViewController 调用此 class ?可能吗?

为了使事情更简单,我首先使用结构和函数从 WebKit 添加了一个 WebView 到视图:

func makeUIView(context: Context) -> WKWebView
func updateUIView(_ uiView: WKWebView, context: Context)

这很好用。现在我必须添加 javascript 兼容性。

因此,如果我遵循我找到的 UIViewController 示例,我发现我必须添加:

let config = WKWebViewConfiguration()
config.userContentController.add(self, name: doSomething) // I'm seeing an error here

错误是:

Argument type 'SwiftUIWebView' does not conform to expected type 'WKScriptMessageHandler'

所以在这里我尝试将 'WKScriptMessageHandler' 添加到结构中(如果我进行扩展也会发生同样的情况):

struct SwiftUIWebView: UIViewRepresentable, WKScriptMessageHandler // Another a couple errors are shown

错误是:

1. Non-class type 'SwiftUIWebView' cannot conform to class protocol 'NSObjectProtocol'
2. Non-class type 'SwiftUIWebView' cannot conform to class protocol 'WKScriptMessageHandler'

所以我想,好吧,让我们从结构更改为 class。现在显示更多错误。其中一些在我为原来的WebView做的两个函数中都有错误,顺序同上:

1. Protocol 'UIViewRepresentable' requirement 'makeUIView(context:)' cannot be satisfied by a non-final class ('SwiftUIWebView') because it uses 'Self' in a non-parameter, non-result type position
2. Protocol 'UIViewRepresentable' requirement 'updateUIView(_:context:)' cannot be satisfied by a non-final class ('SwiftUIWebView') because it uses 'Self' in a non-parameter, non-result type position

所以我认为我的方向不对。

据我所知,我相信这些实现 UIViewController 协议的 classes 是基于故事板的项目的视图。 例如,this link 是我关注的链接之一,因为它有一个 GitHub 回购链接,它不仅仅是代码片段。

我可以在 Swift 项目中使用此功能吗?如果是这样,怎么做?

SwiftUI 视图必须是 structs,因此您需要创建一个单独的 class 符合 WKScriptMessageHandler 协议并将该 class 的实例存储在你的 WebView.

struct WebView: UIViewRepresentable {
    private let messageHandler: WebKitMessageHandler

    init(messageHandler: WebKitMessageHandler) {
        self.messageHandler = messageHandler
    }

    func makeUIView(context: Context) -> WKWebView {
        let config = WKWebViewConfiguration()
        config.userContentController.add(messageHandler, name: "name")
        // pass appropriate frame here
        let webView = WKWebView(frame: CGRect.zero, configuration: config)
        return webView
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {

    }
}

class WebKitMessageHandler: NSObject, WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

    }
}