未附加到视图层次结构时,WKWebKit javascript 执行 [英] WKWebKit javascript execution when not attached to a view hierarchy

查看:52
本文介绍了未附加到视图层次结构时,WKWebKit javascript 执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从 UIWebView 切换到 WKWebView.在我的代码中,web 视图实例是在屏幕外创建的(不附加到视图层次结构)并加载 URL.加载完成后,Web 视图会在单独的 UIWindow(如插页式广告)中呈现给用户.UIWebView 一切正常;但是在切换到 WKWebView 后,angular javascript 代码的行为出乎意料.

经过一些研究,我发现当 WKWebView 实例未附加到视图层次结构时,javascript 计时器(和 HTTP 加载器)会暂停:如果您在 javascript 中启动计时器,在分离的 WKWebView 中运行 - 在附加 web 视图之前它不会被触发.

谁能提出可能的解决方法(除了将隐藏的 Web 视图附加到关键窗口然后将其移动到另一个窗口之外)?

我已经创建了一个示例项目来演示该问题(或者更有可能是 WebKit 功能)

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

测试应用程序使用 javascript 加载网页,该网页会安排计时器并加载 HTTP 请求.您可以使用开关来显示/隐藏 Web 视图(设置隐藏"属性)并将其从视图层次结构中附加/分离.

如果网络视图已附加(隐藏或可见)并且您点击 Load,则 javascript 工作正常:您可以看到 successfailure 警报对话框.如果它是分离的 - 计时器只会在它附加到视图层次结构时触发(将分离"切换为打开",点击加载",等待几秒钟并切换回关闭").您还可以从 Safari Web Inspector 检查 console.log.

这是测试网页源:

<html ng-app="项目"><头><脚本src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.js"></script><script src="project.js"></script><身体><div id="simple" ng-controller="MyController" data-ng-init="callNotify(message);">

</html>

还有 javascript:

角度.模块('项目',[]).控制器('MyController', ['$scope','notify', function ($scope, notify) {$scope.callNotify = 函数(味精){通知(味精);};}]).factory('notify', ['$window', '$http', '$q', '$timeout', function(win, $http, $q, $timeout) {返回函数(味精){延期 = $q.defer();$超时(功能(){$http.get('http://jsonplaceholder.typicode.com/posts').成功(功能(数据,状态,标题,配置){警报(成功");console.log("成功")}).错误(功能(数据,状态,标题,配置){警报(错误");console.log("错误")});});返回 deferred.promise;};}]);

解决方案

遇到了同样的问题,除了将 WKWebView 添加到视图层次结构并使用 AutoLayout 将其移出屏幕之外,我从未找到任何解决方案.幸运的是,这种变通办法确实有效.

I want to switch to WKWebView from UIWebView. 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 UIWebView; but after switching to WKWebView, the angular javascript code behaves in an unexpected way.

After doing some research, I've figured out that javascript timers (and HTTP loaders) are suspended when the WKWebView instance is not attached to the view hierarchy: if you start a timer in javascript which runs in detached WKWebView - it won't be fired until the web view is attached.

Can anyone suggest a possible workaround (besides attaching a hidden web view to the key window and then moving it to another window)?

I've created a sample project to demonstrate the issue (or, more likely, a WebKit feature)

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

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.

If the web view is attached (hidden or visible) and you hit Load, the javascript works fine: you can see success or failure 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 console.log from Safari Web Inspector.

Here's the test web page source:

<!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>

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

解决方案

Having run into the same problem, I never found any solution except to add the WKWebView to the view hierarchy and move it offscreen with AutoLayout. Fortunately, this workaround does work reliably.

这篇关于未附加到视图层次结构时,WKWebKit javascript 执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆