Ошибка webkit окна postMessage iOS Swift

Я пытаюсь создать библиотеку, которая открывает веб-представление в классе, где цель открывается, но не отображается на экране. Я создал и пытаюсь выполнить javaScript, который создает postMessage, чтобы получить результат, например, в методе userContentController(), но я получаю ошибку при его выполнении. Кроме того, я использую webView.callAsyncJavaScript, потому что тогда я хочу выполнить некоторые асинхронные функции, которые webView.evaluateJavaScript не позволяет. Кое-кто знает, в чем может быть причина, которая может мне помочь. Спасибо.

Код:

      import WebKit

class FingerprintJs : NSObject, WKScriptMessageHandler, WKNavigationDelegate{
    
    public func tryFinger(){
        getWebView()
    }
    
    public func userContentController(_ userContentController: WKUserContentController,
                                      didReceive message: WKScriptMessage){
        print("userContentController")
        print(message.name)
    }
    
    private func getWebView(){
        if let viewController = UIWindow.key?.rootViewController {
            if Thread.isMainThread {
                let webView = self.makeWebView(viewController: viewController as! ViewController)
                webView.loadHTMLString(getHtml(), baseURL: nil)
                if #available(iOS 14.0, *) {
                    print("bunea")
                    webView.callAsyncJavaScript(getJavaScript()!, arguments: [:], in: nil, in: .defaultClient, completionHandler:{(result) in
                        print("queeeeee")
                        print(result as Any)
                    })
                } else {
                    print("Llegaste aca? porqueee ")
                    // Fallback on earlier versions
                }
//                webView.evaluateJavaScript(getJavaScript()!,completionHandler:{(result , error) in
//                    if error == nil {
//                        print("success")
//                        print(result as Any)
//                    }
//                    else {
//                        print("error in executing js ", error!)
//                    }
//                })
            } else {
               print("Llegaste aca? ")
            }

            
        }else{
            NSLog("The UIApplication keyWindow of the rootViewController must be loaded first", "")
        }
    }
        
    private func makeWebView(viewController: ViewController) -> WKWebView {
        let preferences = WKPreferences()
        preferences.javaScriptEnabled = true
        let config = WKWebViewConfiguration()
        config.userContentController.add(self, name: "message5")
        config.preferences = preferences
        let webView = WKWebView(frame: .init(x: 1.0, y: 1.0, width: 0, height: 0),
                                configuration: config)
        webView.translatesAutoresizingMaskIntoConstraints = false
        viewController.view.addSubview(webView)
        return webView
    }
    
    private func getJavaScript() -> String?{
        var javaScript: String? = nil
        if let jsSourcePath = Bundle.main.path(forResource: "ejemplo", ofType: "js") {
            do {
                javaScript = try String(contentsOfFile: jsSourcePath)
            }
            catch {
                NSLog("getJavaScriptString: "+(error.localizedDescription), "")
            }
        }
        return javaScript
    }
    
    private func getHtml() -> String {
        let html: String =
            """
            <html>
                <body>
                    <script>
                    </script>
                </body>
            </html>
            """
        return html
    }
    
    private var webView: WKWebView? {
        didSet {
            oldValue?.removeFromSuperview()
            oldValue?.configuration.userContentController.removeScriptMessageHandler(forName: "message5")
        }
    }
    
   
}

extension UIWindow {
    static var key: UIWindow? {
        if #available(iOS 13, *) {
            return UIApplication.shared.windows.first { $0.isKeyWindow }
        } else {
            return UIApplication.shared.keyWindow
        }
    }
}

Javascript :

      testFunct();
function testFunct() {
    window.webkit.messageHandlers.message5.postMessage("nice" )
}

Ошибка :

      failure(Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=0, WKJavaScriptExceptionMessage=TypeError: undefined is not an object (evaluating 'window.webkit.messageHandlers'), WKJavaScriptExceptionColumnNumber=0, NSLocalizedDescription=A JavaScript exception occurred})

Кроме того, например, здесь у меня есть некоторые изменения кода, но, например, я никогда не получаю в методе userContentController сообщение. Где я установил window.webkit.messageHandlers в html.

      import WebKit
import UIKit

class FingerprintJs : NSObject, WKScriptMessageHandler, WKNavigationDelegate{
    
    public func tryFinger(){
        getWebView()
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        assert(message.name == "myMessageName")
    }
    
    private func getWebView(){
        if let viewController = UIWindow.key?.rootViewController {
            if Thread.isMainThread {
                let webView = self.makeWebView(viewController: viewController as! ViewController)
                webView.loadHTMLString(getHtml(), baseURL: nil)
//                webView.evaluateJavaScript(getJavaScript()!,completionHandler:{(result , error) in
//                    if error == nil {
//                        print("success")
//                        print(result as Any)
//                    }
//                    else {
//                        print("error in executing js ", error!)
//                    }
//                })
            } else {
               print("Llegaste aca? ")
            }

            
        }else{
            NSLog("The UIApplication keyWindow of the rootViewController must be loaded first", "")
        }
    }
        
    private func makeWebView(viewController: ViewController) -> WKWebView {
        let preferences = WKPreferences()
        preferences.javaScriptEnabled = true
        let config = WKWebViewConfiguration()
        config.userContentController.add(self, name: "myMessageName")
        config.preferences = preferences
        let webView = WKWebView(frame: .init(x: 1.0, y: 1.0, width: 0, height: 0),
                                configuration: config)
        webView.translatesAutoresizingMaskIntoConstraints = false
        viewController.view.addSubview(webView)
        webView.navigationDelegate = self
        return webView
    }
    
    private func getJavaScript() -> String?{
        var javaScript: String? = nil
        if let jsSourcePath = Bundle.main.path(forResource: "ejemplo", ofType: "js") {
            do {
                javaScript = try String(contentsOfFile: jsSourcePath)
            }
            catch {
                NSLog("getJavaScriptString: "+(error.localizedDescription), "")
            }
        }
        return javaScript
    }
    
    private func getHtml() -> String {
        let html: String =
            """
            <html>
                <body>
                    <script>
                        window.webkit.messageHandlers.myMessageName.postMessage("message")
                    </script>
                </body>
            </html>
            """
        return html
    }
    
    private var webView: WKWebView? {
        didSet {
            oldValue?.removeFromSuperview()
            oldValue?.configuration.userContentController.removeScriptMessageHandler(forName: "message5")
        }
    }
    
   
}

extension UIWindow {
    static var key: UIWindow? {
        if #available(iOS 13, *) {
            return UIApplication.shared.windows.first { $0.isKeyWindow }
        } else {
            return UIApplication.shared.keyWindow
        }
    }
}

1 ответ

      func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("testFunct()")
}

попробуйте вызвать метод JS из метода навигации didFinish после загрузки веб-представления. Это может быть связано с вызовом метода JS до того, как веб-представление будет загружено должным образом.

Другие вопросы по тегам