检测页面是不是在 JavaScript 中的 WKWebView 中加载
Posted
技术标签:
【中文标题】检测页面是不是在 JavaScript 中的 WKWebView 中加载【英文标题】:Detect if page is loaded inside WKWebView in JavaScript检测页面是否在 JavaScript 中的 WKWebView 中加载 【发布时间】:2015-03-01 15:44:24 【问题描述】:如何使用 javascript 可靠地检测页面是否加载到 WKWebView 中?我希望能够检测到这些场景:
ios 和 WKWebView iOS 和 Safari 不是 iOS关于 UIWebView here 也有类似的问题。但它已经很老了,我不确定 WKWebView 是否仍然适用。
【问题讨论】:
为什么?也许我们可以为您提供更好的方法来实现您的基本目标。 您不确定其他问题中描述的方法是否有效。那就试试吧! 如果在 WKWebView 中加载,页面的某些功能会有所不同。例如,它将使用原生类来优化文件上传。 我尝试了所有这些解决方案,但对我不起作用,请参阅我的answer 【参考方案1】:接受的答案在使用WKWebView vs UIWebView app 测试时不起作用
正如文章所述,唯一的 html5 功能差异是 IndexedDB 支持。所以我会选择一个更可靠的模式:
if (navigator.platform.substr(0,2) === 'iP')
//iOS (iPhone, iPod or iPad)
var lte9 = /constructor/i.test(window.HTMLElement);
var nav = window.navigator, ua = nav.userAgent, idb = !!window.indexedDB;
if (ua.indexOf('Safari') !== -1 && ua.indexOf('Version') !== -1 && !nav.standalone)
//Safari (WKWebView/Nitro since 6+)
else if ((!idb && lte9) || !window.statusbar.visible)
//UIWebView
else if ((window.webkit && window.webkit.messageHandlers) || !lte9 || idb)
//WKWebView
您可能会问:为什么不使用 UserAgent?那是因为安卓浏览器使用它作为设置!所以,我们永远不应该相信任何 UA。仅限浏览器功能和属性检查。
我还注意到QuickTime
插件总是作为旧版 Safari 和 UIWebView 中其他浏览器的一部分加载。但是该插件不再存在于 WKWebView 中。所以你可以使用QuickTime
插件作为额外的检查。
9/23/16 编辑:我调整了 Safari 10 的代码,它不再允许唯一的 idb 检查是可靠的,正如 @xmnboy 所提到的。要放弃 Safari 10,它会检查旧的 webkit 引擎错误,该错误仅适用于 Safari 9.2;我使用了window.statusbar.visible
后备,在 iOS 9 和 10 之间进行了几次比较测试后,这似乎是一个可靠的指标信号。(请检查)
【讨论】:
不幸的是,这种方法不再有效。它在 iOS 9 设备上运行良好,但在 iOS 10 设备上,即使您在 UIWebView 中,对 window.indexedDB 的检查也会出现。 @xmnboy 好的,这并不奇怪。我有点怀疑这可能会发生。我要检查一下并寻找替代方案。 @xmnboy 我忘记了我实际上已经找到了另一个后备方案,在我的脚本中作为评论留下了方便,这似乎仍然是正确的,并且是 iOS10 的有效后备方案。 感谢您对检测机制的更新。 :-)window.statusbar.visible
对我们不起作用——在我们应用程序的 iOS10.3 上的 WKWebkitView 中确实如此。也许是因为我们的应用是全屏的?见wantsFullScreenLayout versus modalPresentationStyle of UIModalPresentationFullScreen。【参考方案2】:
鉴于 Apple 在 iOS 10 中引入的 UIWebView 的行为变化,这里有一个新的答案,它结合了 @Justin-Michael 的原始回复和 @hexalys 的后续最爱。
var isWKWebView = false ;
if( navigator.platform.substr(0,2) === 'iP' ) // iOS detected
if( window.webkit && window.webkit.messageHandlers )
isWKWebView = true ;
事实证明,Justin 的回答确实是更好的特征检测机制,因为它适用于 iOS 9 和 iOS 10。
不知道当我们进入 iOS 11 时会发生什么。:-)
资格:如果您使用 official Cordova WKWebView plugin 构建您的 webview 应用程序,此测试将有效,因为该插件确实初始化了 addScriptMessageHandler
方法,正如 cmets 中的 @hexalys 所指出的那样这个帖子。当存在 WKWebView 插件时,Cordova 正在使用该机制来定义一个新的 JS 到本机桥。
在that plugin repo 中搜索addScriptMessageHandler
并查看该repo 中the ios-wkwebview-exec.js
file 的最后部分以了解一些实现细节(或在该文件中搜索字符串window.webkit.messageHandlers
)。
【讨论】:
同样,尽管 webkit 并不总是默认情况下在所有 iOS 视图上定义的对象。所以在 JS 方面不可靠。正如this answer 所述。 “window.webkit 命名空间仅出现在带有脚本消息处理程序的 webview 中。确保您已调用 WKUserContentController 的 addScriptMessageHandler 方法。”例如测试应用肯定没有设置它。 @hexalys -- 感谢您提供的额外知识。我已经更新了我的答案,包括关于我的测试环境的资格。我只关心在 Cordova(又名 Adobe PhoneGap 或 Intel XDK)构建环境中检测到 WKWebVew。【参考方案3】:似乎是因为最新的iOS Chrome 使用WKWebView 作为渲染引擎,Chrome 被检测为WKWebView。 ua.indexOf('CriOS') !== -1 将有助于区分 Chrome 和 App 中的 WKWebView。
【讨论】:
【参考方案4】:在iOS中,你可以添加这段代码来建立javascript和objective-c之间的通信:
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *controller = [[WKUserContentController alloc] init];
[controller addScriptMessageHandler:self name:@"javascript_observer"];
configuration.userContentController = controller;
...
webview = [[WKWebView alloc] initWithFrame:... configuration: configuration];
在 javascript 中,您可以像这样测试连接:
if ( window.webkit != undefined )
//javascript is running in webview
【讨论】:
【参考方案5】:您可以检查 WKWebKit 用于接收来自 JavaScript 的消息的 window.webkit.messageHandlers
是否存在。如果它存在,那么您就在 WKWebView
中。
结合简单的用户代理检查应该可以解决问题:
var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false);
var isWKWebView = false;
if (window.webkit && window.webkit.messageHandlers)
isWKWebView = true;
【讨论】:
这听起来是个不错的解决方案。与 iOS 检查一起,它应该提供可靠的结果。 iOS 测试是错误的,因为它使用了用户代理(还检测到 android、WinPhone 8.1 更新等)。 /^iPhone|^iPad|^iPod/.test(navigator.platform) 之类的东西更好。请注意,“iPod touch”用于 iOS 8,因此请勿在 iPod 后添加 $。 这是唯一有效的答案。不是 iOS 检查,而是 messageHandlers 检查。以上是关于检测页面是不是在 JavaScript 中的 WKWebView 中加载的主要内容,如果未能解决你的问题,请参考以下文章
如何在客户端使用 JavaScript 来检测页面是不是已加密?
使用 javascript/jquery 检测 Asp.Net 表单是不是有效
如何检测 Javascript 中的页面宽度和高度? [复制]