title: Window webkit failure postMessage iOS Swift
body: <p>I am trying to create a library that open a web view in a class, where the objetive is opened it but does not see it in the screen. I created and try to execute a javaScript that makes a postMessage, to obtain the result for example in the method userContentController(), but I am getting and error when I execute it. Also, I am used webView.callAsyncJavaScript, cause then I want to execute some async functions that webView.evaluateJavaScript does not let. Some knows what could be the reason that can help me. Thanks.</p>
  <p><strong>Code:</strong></p>
  <pre><code>import WebKit
  
  class FingerprintJs : NSObject, WKScriptMessageHandler, WKNavigationDelegate{
      
      public func tryFinger(){
          getWebView()
      }
      
      public func userContentController(_ userContentController: WKUserContentController,
                                        didReceive message: WKScriptMessage){
          print(&quot;userContentController&quot;)
          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(&quot;bunea&quot;)
                      webView.callAsyncJavaScript(getJavaScript()!, arguments: [:], in: nil, in: .defaultClient, completionHandler:{(result) in
                          print(&quot;queeeeee&quot;)
                          print(result as Any)
                      })
                  } else {
                      print(&quot;Llegaste aca? porqueee &quot;)
                      // Fallback on earlier versions
                  }
  //                webView.evaluateJavaScript(getJavaScript()!,completionHandler:{(result , error) in
  //                    if error == nil {
  //                        print(&quot;success&quot;)
  //                        print(result as Any)
  //                    }
  //                    else {
  //                        print(&quot;error in executing js &quot;, error!)
  //                    }
  //                })
              } else {
                 print(&quot;Llegaste aca? &quot;)
              }
  
              
          }else{
              NSLog(&quot;The UIApplication keyWindow of the rootViewController must be loaded first&quot;, &quot;&quot;)
          }
      }
          
      private func makeWebView(viewController: ViewController) -&gt; WKWebView {
          let preferences = WKPreferences()
          preferences.javaScriptEnabled = true
          let config = WKWebViewConfiguration()
          config.userContentController.add(self, name: &quot;message5&quot;)
          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() -&gt; String?{
          var javaScript: String? = nil
          if let jsSourcePath = Bundle.main.path(forResource: &quot;ejemplo&quot;, ofType: &quot;js&quot;) {
              do {
                  javaScript = try String(contentsOfFile: jsSourcePath)
              }
              catch {
                  NSLog(&quot;getJavaScriptString: &quot;+(error.localizedDescription), &quot;&quot;)
              }
          }
          return javaScript
      }
      
      private func getHtml() -&gt; String {
          let html: String =
              &quot;&quot;&quot;
              &lt;html&gt;
                  &lt;body&gt;
                      &lt;script&gt;
                      &lt;/script&gt;
                  &lt;/body&gt;
              &lt;/html&gt;
              &quot;&quot;&quot;
          return html
      }
      
      private var webView: WKWebView? {
          didSet {
              oldValue?.removeFromSuperview()
              oldValue?.configuration.userContentController.removeScriptMessageHandler(forName: &quot;message5&quot;)
          }
      }
      
     
  }
  
  extension UIWindow {
      static var key: UIWindow? {
          if #available(iOS 13, *) {
              return UIApplication.shared.windows.first { $0.isKeyWindow }
          } else {
              return UIApplication.shared.keyWindow
          }
      }
  }
  </code></pre>
  <p><strong>Javascript</strong>:</p>
  <pre><code>testFunct();
  function testFunct() {
      window.webkit.messageHandlers.message5.postMessage(&quot;nice&quot; )
  }
  </code></pre>
  <p><strong>Error</strong>:</p>
  <pre><code>failure(Error Domain=WKErrorDomain Code=4 &quot;A JavaScript exception occurred&quot; UserInfo={WKJavaScriptExceptionLineNumber=0, WKJavaScriptExceptionMessage=TypeError: undefined is not an object (evaluating 'window.webkit.messageHandlers'), WKJavaScriptExceptionColumnNumber=0, NSLocalizedDescription=A JavaScript exception occurred})
  </code></pre>
  <p>In addition for example here I have some changes of code but for example I never receive in method userContentController the message. Where I set the window.webkit.messageHandlers in the html.</p>
  <pre><code>import WebKit
  import UIKit
  
  class FingerprintJs : NSObject, WKScriptMessageHandler, WKNavigationDelegate{
      
      public func tryFinger(){
          getWebView()
      }
      
      func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
          assert(message.name == &quot;myMessageName&quot;)
      }
      
      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(&quot;success&quot;)
  //                        print(result as Any)
  //                    }
  //                    else {
  //                        print(&quot;error in executing js &quot;, error!)
  //                    }
  //                })
              } else {
                 print(&quot;Llegaste aca? &quot;)
              }
  
              
          }else{
              NSLog(&quot;The UIApplication keyWindow of the rootViewController must be loaded first&quot;, &quot;&quot;)
          }
      }
          
      private func makeWebView(viewController: ViewController) -&gt; WKWebView {
          let preferences = WKPreferences()
          preferences.javaScriptEnabled = true
          let config = WKWebViewConfiguration()
          config.userContentController.add(self, name: &quot;myMessageName&quot;)
          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() -&gt; String?{
          var javaScript: String? = nil
          if let jsSourcePath = Bundle.main.path(forResource: &quot;ejemplo&quot;, ofType: &quot;js&quot;) {
              do {
                  javaScript = try String(contentsOfFile: jsSourcePath)
              }
              catch {
                  NSLog(&quot;getJavaScriptString: &quot;+(error.localizedDescription), &quot;&quot;)
              }
          }
          return javaScript
      }
      
      private func getHtml() -&gt; String {
          let html: String =
              &quot;&quot;&quot;
              &lt;html&gt;
                  &lt;body&gt;
                      &lt;script&gt;
                          window.webkit.messageHandlers.myMessageName.postMessage(&quot;message&quot;)
                      &lt;/script&gt;
                  &lt;/body&gt;
              &lt;/html&gt;
              &quot;&quot;&quot;
          return html
      }
      
      private var webView: WKWebView? {
          didSet {
              oldValue?.removeFromSuperview()
              oldValue?.configuration.userContentController.removeScriptMessageHandler(forName: &quot;message5&quot;)
          }
      }
      
     
  }
  
  extension UIWindow {
      static var key: UIWindow? {
          if #available(iOS 13, *) {
              return UIApplication.shared.windows.first { $0.isKeyWindow }
          } else {
              return UIApplication.shared.keyWindow
          }
      }
  }
  </code></pre>