Swift WkMessageHandler 消息不发送

问题描述 投票:0回答:1

我正在使用 YouTube 短片创建 TikTok 克隆,我想获取视频长度。为此,我在嵌入 html 中创建了一个函数,该函数使用 WKScriptMessageHandler 发布消息,并且

userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage){
函数应该获取此消息并更新totalLength 变量。

但这目前不起作用。该消息永远不会发送,因此上面的函数永远不会执行。但是 html func

sendCurrentTime()
会在 WKWebView 加载完成时执行。我怎样才能找出为什么这条消息没有发送?

据我所知,消息未发送,因为 Web 视图配置不正确或 html 无法访问 Web 视图对象。

struct SmartReelView: UIViewRepresentable {
    let link: String
    @Binding var totalLength: Double

    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: "observe")
        webview.configuration.userContentController = userContentController

        loadInitialContent(web: webview)
        
        return webview
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) { }
    
    class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
        var parent: SmartReelView

        init(_ parent: SmartReelView) {
            self.parent = parent
        }
        
        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage){
            if message.name == "observe", let Time = message.body as? Double {
                parent.totalLength = Time
            }
        }
        
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("sendCurrentTime()", completionHandler: nil)
        }
    }
    
    private func loadInitialContent(web: 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 = false;
            function onYouTubeIframeAPIReady() {
                player = new YT.Player('player', {
                    width: '100%',
                    videoId: '\(link)',
                    playerVars: { 'playsinline': 1, 'controls': 0},
                    events: {
                        'onStateChange': function(event) {
                            if (event.data === YT.PlayerState.ENDED) {
                                player.seekTo(0);
                                player.playVideo();
                            }
                        }
                    }
                });
            }
            function sendCurrentTime() {
                const length = player.getDuration();
                window.webkit.messageHandlers.observe.postMessage(length);
            }
        </script>
        """
        
        web.scrollView.isScrollEnabled = false
        web.loadHTMLString(embedHTML, baseURL: nil)
    }
}
html ios swift youtube wkwebview
1个回答
0
投票

我对自己的项目做了一个快速测试。看来将配置传递给 Webview 的顺序很重要。

这是行不通的。如果首先使用默认配置初始化 Web 视图,则无法获取回调

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: "observe")
webview.configuration.userContentController = userContentController

这有效!

let userContentController = WKUserContentController()
userContentController.add(context.coordinator, name: "observe")

let webConfiguration = WKWebViewConfiguration()
webConfiguration.allowsInlineMediaPlayback = true
webConfiguration.userContentController = userContentController

let webview = WKWebView(frame: .zero, configuration: webConfiguration)
webview.navigationDelegate = context.coordinator
© www.soinside.com 2019 - 2024. All rights reserved.