title: WKWebKit javascript execution when not attached to a view hierarchy
body: <p>I want to switch to <code>WKWebView</code> from <code>UIWebView</code>. In my code, the web view instance is created offscreen (without attaching to the view hierarchy) and URL is loaded. When loading is done, the web view is presented to the user in a separate UIWindow (like an interstitial ad). Everything works fine with <code>UIWebView</code>; but after switching to <code>WKWebView</code>, the angular javascript code behaves in an unexpected way.</p>
  
  <p>After doing some research, I've figured out that javascript timers (and HTTP loaders) are suspended when the <code>WKWebView</code> instance is not attached to the view hierarchy: if you start a timer in javascript which runs in detached <code>WKWebView</code> - it won't be fired until the web view is attached.</p>
  
  <p>Can anyone suggest a possible workaround (besides attaching a hidden web view to the key window and then moving it to another window)?</p>
  
  <p>I've created a sample project to demonstrate the issue (or, more likely, a WebKit feature)</p>
  
  <p><a href="https://dl.dropboxusercontent.com/u/148568148/WebKitViewTest.zip" rel="noreferrer">https://dl.dropboxusercontent.com/u/148568148/WebKitViewTest.zip</a></p>
  
  <p>The test application loads a web page with javascript which schedules a timer and loads HTTP request. You can use switches to show/hide web view (sets 'hidden' property) and attach/detach it from the view hierarchy.</p>
  
  <p><img src="https://i.stack.imgur.com/wUAdo.png" alt="Sample app running on iOS 8.0"></p>
  
  <p>If the web view is attached (hidden or visible) and you hit <code>Load</code>, the javascript works fine: you can see <code>success</code> or <code>failure</code> alert dialog. If it's detached - the timer will only fire when it's attached to the view hierarchy (switch "Detached" to "on", hit "Load", wait a couple of seconds and switch back to "off"). You can also check <code>console.log</code> from Safari Web Inspector.</p>
  
  <p>Here's the test web page source:</p>
  
  <pre><code>&lt;!doctype html&gt;
  &lt;html ng-app="project"&gt;
    &lt;head&gt;
      &lt;script
        src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.js"&gt;&lt;/script&gt;
      &lt;script src="project.js"&gt;&lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;
      &lt;div id="simple" ng-controller="MyController" data-ng-init="callNotify(message);"&gt;
      &lt;/div&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>And the javascript:</p>
  
  <pre><code>angular.
    module('project', []).
    controller('MyController', ['$scope','notify', function ($scope, notify) {
    $scope.callNotify = function(msg) {
      notify(msg);
    };
  }]).
    factory('notify', ['$window', '$http', '$q', '$timeout', function(win, $http, $q, $timeout) {
    return function(msg) {
      deferred = $q.defer();
  
      $timeout(function() {
        $http.get('http://jsonplaceholder.typicode.com/posts').
        success(function(data, status, headers, config) {
          alert("success");
          console.log("success")
        }).
          error(function(data, status, headers, config) {
          alert("error");
          console.log("error")
        });
      });
      return deferred.promise;
    };
  }]);
  </code></pre>