【问题标题】:Swift project with Javascript two way communicationSwift 项目与 Javascript 双向通信
【发布时间】:2022-01-22 18:36:29
【问题描述】:

我正在构建一个 iOS Swift 应用程序,我希望通过 javascript 进行双向通信。从 javascript 我需要监听消息 (json) 并发送 jsons。 我知道有很多帖子解决了这个问题,但由于我是 iOS 开发新手,所以我无法让它工作。

根据我在其他响应和/或其他教程页面(例如 medium)中看到的内容,为了做到这一点,他们构建了一个实现 UIViewController 协议的类。但我的视图是一个实现协议视图的结构。如何从我的视图中使用协议 UIViewController 调用此类?有可能吗?

为了让事情更简单,我首先使用结构和函数将 WebKit 中的 WebView 添加到 View 中:

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'

所以我想,好吧,让我们从结构更改为类。现在显示的错误更多。其中一些在我为原始 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 协议的类是来自基于故事板的项目的视图。 例如,this link 是我关注的链接之一,因为它链接了一个 GitHub 存储库,而不仅仅是代码片段。

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

【问题讨论】:

    标签: javascript ios swift swiftui webkit


    【解决方案1】:

    SwiftUI 视图必须是structs,因此您需要创建一个单独的符合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) {
    
        }
    }
    

    【讨论】:

    • 感谢您的回复,我正在查看。可以肯定的是,在视图中我应该这样称呼它: WebView(messageHandler: WebKitMessageHandler()) ?
    • @PauDC 是的,你应该这样创建它
    • 非常感谢,我会立即将其标记为解决方案。我花了一段时间来完全测试它,因为一旦进入 WebKitMessageHandler,我就找不到 WebView 来调用 evaluateJavaScript。我在 WKScriptMessage 中找到了它。
    猜你喜欢
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 2016-06-06
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    相关资源
    最近更新 更多