Выполнение javascript WKWebKit, если оно не привязано к иерархии представлений

Я хочу переключиться на WKWebView с UIWebView. В моем коде экземпляр веб-представления создается вне экрана (без привязки к иерархии представления), и URL-адрес загружается. Когда загрузка будет завершена, веб-представление будет представлено пользователю в отдельном UIWindow (например, в промежуточной рекламе). Все отлично работает с UIWebView; но после переключения на WKWebView angular код javascript ведет себя неожиданным образом.

Проведя некоторые исследования, я выяснил, что таймеры javascript (и загрузчики HTTP) приостанавливаются, когда экземпляр WKWebView не присоединен к иерархии представления: если вы запускаете таймер в javascript, который работает в отдельном WKWebView - он не будет запущен, пока не будет прикреплено веб-представление.

Кто-нибудь может предложить возможный обходной путь (помимо присоединения скрытого веб-вида к ключевому окну и затем перемещения его в другое окно)?

Я создал образец проекта, чтобы продемонстрировать проблему (или, более вероятно, функцию WebKit)

https://dl.dropboxusercontent.com/u/148568148/WebKitViewTest.zip

Тестовое приложение загружает веб-страницу с JavaScript, который планирует таймер и загружает HTTP-запрос. Вы можете использовать переключатели, чтобы показать/скрыть веб-представление (задает свойство 'hidden') и прикрепить/отсоединить его от иерархии представления.

Sample app running on iOS 8.0

Если веб-вид прикреплен (скрыт или видим), и вы нажали Load, JavaScript прекрасно работает: вы можете увидеть диалоговое окно с предупреждением success или failure. Если он отключен - таймер сработает только тогда, когда он подключен к иерархии представлений (переключите "Detached" в "on", нажмите "Load", подождите пару секунд и снова переключитесь в "off"). Вы также можете проверить console.log в Safari Web Inspector.

Вот источник тестовой веб-страницы:

<!doctype html>
<html ng-app="project">
  <head>
    <script
      src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.js"></script>
    <script src="project.js"></script>
  </head>
  <body>
    <div id="simple" ng-controller="MyController" data-ng-init="callNotify(message);">
    </div>
  </body>
</html>

И JavaScript:

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;
  };
}]);

Ответы

Ответ 1

Столкнувшись с той же проблемой, я никогда не находил никакого решения, кроме как добавить WKWebView в иерархию представления и переместить его за экран с помощью AutoLayout. К счастью, этот обходной путь работает надежно.