Swift WkMessageHandler消息不发送

toe95027  于 2023-09-30  发布在  Swift
关注(0)|答案(1)|浏览(131)

我正在使用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)
    }
}
3pvhb19x

3pvhb19x1#

我在自己的项目上做了一个快速测试。似乎将配置传递给Webview的顺序很重要。
这行不通。如果在未设置userContentController的情况下首先初始化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

相关问题