如何从嵌入式HTML向Swift通信修改Bool绑定变量
问题:在HTML的onReady回调中修改Swift的@Binding布尔变量
我需要在HTML的onReady代码块执行时,修改Swift中名为click的@Binding布尔变量。目前已通过evaluateJavaScript实现Swift向HTML的通信,但不清楚如何从HTML的onReady回调向Swift传递消息来修改该Bool变量的值。我尝试创建了Coordinator类,初始代码如下:
struct SmartReelView: UIViewRepresentable { let link: String @Binding var isPlaying: Bool @Binding var click: Bool // 需要修改的变量 func makeUIView(context: Context) -> WKWebView { let webConfiguration = WKWebViewConfiguration() webConfiguration.allowsInlineMediaPlayback = true let webView = WKWebView(frame: .zero, configuration: webConfiguration) loadInitialContent(in: webView) return webView } func updateUIView(_ uiView: WKWebView, context: Context) { let jsString = "isPlaying = \((isPlaying) ? \"true\" : \"false\"); watchPlayingState();" uiView.evaluateJavaScript(jsString, completionHandler: nil) } private func loadInitialContent(in webView: WKWebView) { let embedHTML = """ <style> body { margin: 0; background-color: black; } .iframe-container iframe { top: 0; left: 0; width: 100%; height: 100%; } </style> <div class="iframe-container"> <div id="player"></div> </div> <script> var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; var isPlaying = true; function onYouTubeIframeAPIReady() { player = new YT.Player('player', { width: '100%', videoId: '\(link)', playerVars: { 'playsinline': 1, 'controls': 0}, events: { 'onReady': function(event) { // 在这里修改Swift变量 }, 'onStateChange': function(event) { if (event.data === YT.PlayerState.ENDED) { player.seekTo(0); player.playVideo(); } } } }); } function watchPlayingState() { if (isPlaying) { player.playVideo(); } else { player.pauseVideo(); } } </script> """ webView.scrollView.isScrollEnabled = false webView.loadHTMLString(embedHTML, baseURL: nil) } }
更新后的代码
根据参考内容修改后的代码如下:
struct SmartReelView: UIViewRepresentable { let link: String @Binding var isPlaying: Bool @Binding var click: Bool func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIView(context: Context) -> WKWebView { let webConfiguration = WKWebViewConfiguration() webConfiguration.allowsInlineMediaPlayback = true let webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.navigationDelegate = context.coordinator let userContentController = WKUserContentController() userContentController.add(context.coordinator, name: "toggleMessageHandler") webView.configuration.userContentController = userContentController loadInitialContent(in: webView) return webView } func updateUIView(_ uiView: WKWebView, context: Context) { let jsString = "isPlaying = \((isPlaying) ? \"true\" : \"false\"); watchPlayingState();" uiView.evaluateJavaScript(jsString, completionHandler: nil) } class Coordinator: NSObject, WKScriptMessageHandler, WKNavigationDelegate { var parent: SmartReelView init(_ parent: SmartReelView) { self.parent = parent } func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "toggleMessageHandler", let messageBody = message.body as? [String: Any] { if let messageValue = messageBody["message"] as? String, messageValue == "click now" { DispatchQueue.main.async { self.parent.click = true } } } } } private func loadInitialContent(in webView: WKWebView) { let embedHTML = """ <style> body { margin: 0; background-color: black; } .iframe-container iframe { top: 0; left: 0; width: 100%; height: 100%; } </style> <div class="iframe-container"> <div id="player"></div> </div> <script> var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; var isPlaying = true; function onYouTubeIframeAPIReady() { player = new YT.Player('player', { width: '100%', videoId: '\(link)', playerVars: { 'playsinline': 1, 'controls': 0}, events: { 'onReady': function(event) { if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.toggleMessageHandler) { window.webkit.messageHandlers.toggleMessageHandler.postMessage({"message": "click now" }); } }, 'onStateChange': function(event) { if (event.data === YT.PlayerState.ENDED) { player.seekTo(0); player.playVideo(); } } } }); } function watchPlayingState() { if (isPlaying) { player.playVideo(); } else { player.pauseVideo(); } } </script> """ webView.scrollView.isScrollEnabled = false webView.loadHTMLString(embedHTML, baseURL: nil) } }
内容的提问来源于stack exchange,提问作者Ahmed Zaidan
相关产品推荐
相关产品推荐

