如何将SwiftUI WebView结构体嵌套类的字符串传递到结构体绑定属性?
如何将ContentController中的response传递给WebView的Binding属性
问题场景
现有一个UIViewRepresentable实现的WebView结构体,内部嵌套的ContentController作为WKScriptMessageHandler,在验证成功(didSolve分支)时获取到了reCaptcha的响应值,需要将这个值传递给WebView的@Binding var response属性,供主ContentView使用。
原始代码片段
struct WebView: UIViewRepresentable { @Binding var response: String func makeUIView(context: Context) -> WKWebView { let webConfiguration = WKWebViewConfiguration() let wkController = WKUserContentController() wkController.add(context.coordinator, name: "reCaptchaiOS") webConfiguration.userContentController = wkController // ... 其他配置代码 return WKWebView(frame: .zero, configuration: webConfiguration) } func updateUIView(_ webView: WKWebView, context: Context) { // ... 更新逻辑 } func makeCoordinator() -> ContentController { ContentController()// let handler be a coordinator } class ContentController: NSObject, WKScriptMessageHandler { // ... 其他属性 var textResponse: String = "" func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if let args = message.body as? [String] { switch args[0] { // ... 其他分支 case "didSolve": self.captchaDidSolve(response: args[1]) textResponse = args[1] break // ... 其他分支 default: print("args[0]: \(args[0])") break } } } func captchaDidSolve(response: String) { print("response: \(response)") } } }
解决方案
只需三步修改,让ContentController直接更新WebView的Binding属性:
给ContentController添加Binding属性
在ContentController类中新增@Binding属性并补充初始化方法,用来持有WebView的response引用:class ContentController: NSObject, WKScriptMessageHandler { @Binding var response: String // 新增Binding属性 var textResponse: String = "" // 新增初始化方法,接收Binding参数 init(response: Binding<String>) { _response = response super.init() } // ... 原有方法保持不变 }在makeCoordinator时传递Binding
修改WebView的makeCoordinator方法,将自身的responseBinding传入ContentController:func makeCoordinator() -> ContentController { ContentController(response: $response) }验证成功时更新Binding值
在captchaDidSolve方法或didSolve分支中直接更新response属性,主ContentView会自动同步这个值:func captchaDidSolve(response: String) { print("response: \(response)") self.response = response // 更新Binding,主视图自动同步 }或者直接在消息处理的分支中更新:
case "didSolve": self.captchaDidSolve(response: args[1]) textResponse = args[1] self.response = args[1] // 直接更新Binding break
说明
通过让ContentController持有WebView的response Binding引用,当内部获取到验证响应时,直接更新该Binding的值即可完成数据传递,主视图的绑定变量会自动同步,无需额外的通知或代理逻辑。
内容的提问来源于stack exchange,提问作者David Leyva Abrahantes
相关产品推荐
相关产品推荐

