如何在Swift中处理JavaScript回调?解决WKScriptMessageHandler兼容错误
解决SwiftUI WebView无法注册WKScriptMessageHandler的问题
要解决Argument type 'WebView' does not conform to expected type 'WKScriptMessageHandler'的错误,核心原因是WKScriptMessageHandler要求实现者为引用类型(类),而UIViewRepresentable的结构体是值类型,不能直接遵守该协议。正确的做法是使用UIViewRepresentable的Coordinator(协调器)来承担消息处理器的角色,具体步骤如下:
1. 定义带协调器的WebView结构体
让协调器继承NSObject并遵守WKScriptMessageHandler协议,同时在WebView中添加用于接收JS消息的闭包(方便将消息传递给SwiftUI视图):
import SwiftUI import WebKit struct WebView: UIViewRepresentable { // 用于接收JS传递的消息,可在SwiftUI视图中绑定处理逻辑 var onMessageReceived: ((String) -> Void)? // 创建协调器,作为WKScriptMessageHandler的实现者 func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> WKWebView { // 配置WebView的用户内容控制器 let userContentController = WKUserContentController() // 注册协调器为"MyHandler"的消息处理器 userContentController.add(context.coordinator, name: "MyHandler") // 配置WebView设置 let configuration = WKWebViewConfiguration() configuration.userContentController = userContentController // 创建WKWebView实例 let webView = WKWebView(frame: .zero, configuration: configuration) // 加载本地HTML文件(示例路径,根据实际情况修改) if let htmlPath = Bundle.main.path(forResource: "index", ofType: "html") { let htmlUrl = URL(fileURLWithPath: htmlPath) webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl.deletingLastPathComponent()) } return webView } func updateUIView(_ uiView: WKWebView, context: Context) {} // 协调器类:继承NSObject并遵守WKScriptMessageHandler class Coordinator: NSObject, WKScriptMessageHandler { var parent: WebView init(_ parent: WebView) { self.parent = parent } // 必须实现的WKScriptMessageHandler方法,处理JS发送的消息 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "MyHandler", let messageBody = message.body as? String { // 将消息传递给WebView的闭包,供SwiftUI视图处理 parent.onMessageReceived?(messageBody) } } } }
2. 在SwiftUI视图中使用该WebView
可以通过绑定onMessageReceived闭包来处理JS传递的消息:
struct ContentView: View { var body: some View { WebView { message in print("收到JS消息:\(message)") // 在这里添加你的业务处理逻辑 } .edgesIgnoringSafeArea(.all) } }
关键说明
- 协调器的作用:Coordinator是类类型,符合WKScriptMessageHandler对引用类型的要求,同时可以通过持有WebView的引用,将JS消息传递给SwiftUI视图。
- 消息处理逻辑:在
userContentController(_:didReceive:)方法中,可根据message.name判断是哪个处理器的消息,并通过message.body获取传递的内容(注意类型转换,根据JS发送的实际类型调整)。 - 本地HTML加载:确保本地HTML文件已添加到项目的Bundle中,路径配置正确。
内容的提问来源于stack exchange,提问作者Gian Gavan
相关产品推荐
相关产品推荐

