You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:45:19