que example app javascript ios uiwebview mobile-safari wkwebview

javascript - example - webview swift 4



Detecta si la página se carga dentro de WKWebView en JavaScript (5)

¿Cómo puedo detectar con seguridad javascript que una página se carga dentro de un WKWebView? Me gustaría poder detectar estos escenarios:

  • iOS y WKWebView
  • iOS y Safari
  • no iOS

Hay una pregunta similar sobre UIWebView aquí . Pero es bastante viejo y no estoy seguro si lo mismo se aplica a WKWebView.


Puede verificar la existencia de window.webkit.messageHandlers que WKWebKit usa para recibir mensajes de JavaScript. Si existe, estás dentro de un WKWebView .

Eso combinado con una simple verificación de agente de usuario debería hacer el truco:

var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? true : false); var isWKWebView = false; if (window.webkit && window.webkit.messageHandlers) { isWKWebView = true; }


Dado el cambio en el comportamiento de UIWebView que Apple introdujo en iOS 10, aquí hay una nueva respuesta que combina la respuesta original de @ Justin-Michael y el favorito de seguimiento de @hexalys.

var isWKWebView = false ; if( navigator.platform.substr(0,2) === ''iP'' ) { // iOS detected if( window.webkit && window.webkit.messageHandlers ) { isWKWebView = true ; } }

Resulta que la respuesta de Justin fue realmente el mejor mecanismo de detección de características, ya que funciona tanto para iOS 9 como para iOS 10.

Sin contar lo que sucede cuando llegamos a iOS 11. :-)

Calificación: esta prueba funcionará si está utilizando el complemento Cordova WKWebView oficial para construir su aplicación de vista web, porque ese complemento inicializa el método addScriptMessageHandler , como lo señala @hexalys en los comentarios de esta publicación. Ese mecanismo está siendo utilizado por Cordova para definir un nuevo puente JS a nativo cuando el plugin WKWebView está presente.

Busque addScriptMessageHandler en ese repositorio de complementos y vea el final del archivo ios-wkwebview-exec.js en ese repositorio para algunos detalles de implementación (o busque la cadena window.webkit.messageHandlers en ese archivo).


La respuesta aceptada no funciona como se probó usando la aplicación WKWebView vs UIWebView

Como se menciona en el artículo, la única diferencia de funciones HTML5 es la compatibilidad con IndexedDB. Así que iría por un patrón más confiable con:

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

Puede preguntar: ¿Por qué no usar el UserAgent? ¡Eso es porque los navegadores de Android lo usan como configuración! Por lo tanto, nunca debemos confiar en ningún UA. Solo las características del navegador y los controles de propiedad como tales.

También noté que el complemento QuickTime siempre se cargaba como parte de Older Safari y otros navegadores en UIWebView. Pero el complemento ya no está presente en WKWebView. Entonces puede usar la presencia del complemento QuickTime como una verificación adicional.

23/9/16 Edición: Ajusté el código de Safari 10 que ya no permitía que el único cheque IDB fuera confiable, como lo menciona @xmnboy. Para descartar Safari 10, busca el viejo error del motor webkit, que solo se aplicó hasta Safari 9.2; y utilizo un window.statusbar.visible fallback que parece ser una señal indicadora confiable después de algunas pruebas de comparación entre iOS 9 y 10. (verifique)


Parece que debido a la última iOS Chrome que usa WKWebView como motor de renderizado, Chrome se detecta como WKWebView. ua.indexOf (''CriOS'')! == -1 ayudará a distinguir Chrome de WKWebView en la aplicación.


En iOS, puede agregar este código para establecer la comunicación entre javascript y object-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];

En javascript, puedes probar la conexión de esta manera:

if ( window.webkit != undefined ){ //javascript is running in webview }