Enviar datos de una UIWebView a una aplicación de iOS con un esquema de URL personalizado se rompe con Xcode 8 / iOS 10

En las versiones de iOS anteriores a 10, pude enviar información de JavaScript / HTML cargada en una UIWebView a mi aplicación creando un iFrame en el documento o configurando document.location.href en una URL personalizada que la vista web intentaría cargar:

 <html> <body><input id="clickMe" type="button" value="clickme" onclick="changeWindow();" /></body> <script type="text/javascript"> function changeWindow() { //create temp frame iFrame = this.createIFrame('onStatusChange://eyJ1c2VyTmFtZSI6IkpBTCIsLCJwcm92aWRlciI6IkVtYWlsIn0='); //remove the frame now iFrame.parentNode.removeChild(iFrame); } function createIFrame(src) { var rootElm = document.documentElement; var newFrameElm = document.createElement('IFRAME'); newFrameElm.setAttribute('src', src); rootElm.appendChild(newFrameElm); return newFrameElm; } </script> </html> 

Luego, en el cliente, simplemente escucharía la UIWebViewDelegate llamada webView:shouldStartLoadWithRequest:navigationType: y webView:shouldStartLoadWithRequest:navigationType: si el request.URL.scheme era igual a mi esquema personalizado (en este caso, onStatusChange ).

Esta es una manera popular de comunicarse entre JavaScript y una aplicación de iOS, como se ve en preguntas populares como Cómo invocar el método Objective C desde Javascript y enviar datos a Javascript en iOS. .

Esto funciona en cualquier aplicación construida con Xcode 7 (Objective-C o Swift) en iOS 9 y 10 dispositivos. Me estoy topando con un problema en el que no se llama al método de delegado en ninguna aplicación creada con Xcode 8. Es como si la vista web ni siquiera tratara de cargar la URL, lo que a su vez no está activando la callback de delegado.

¿Hubo algún cambio en UIWebView o en WebKit desde Xcode 7 a 8 o iOS 9 a 10, lo que provocaría que esto no funcione? Lo que realmente me desconcierta es que una aplicación de producción que he creado con Objective-C en Xcode 7 para iOS 8 funciona con un dispositivo iOS 10, pero una compilation de debugging creada con Xcode 8 de la misma base de código no funciona.

Bien, larga historia, utilizamos un esquema de URL especial en onStatusChange:// para enviar datos codificados Base64 desde la vista web a nuestra aplicación iOS. Creo que UIWebView en iOS 10 se bloquea al intentar cargar una URL que termina en uno o más signos de signos iguales, y se carga about:blank lugar de la URL real.

Dado que esto funciona perfectamente en iOS 9, rdar://29035522 este es un defecto con iOS 10 y he abierto rdar://29035522 . Un ejemplo reproducible completo del problema está disponible en el cuerpo de ese radar.

Estoy leyendo a través del RFC de encoding Base-N para determinar si es aceptable eliminar los caracteres de relleno = al final de mi cadena de datos, o si necesitan ser eliminados de la web y agregarse al cliente antes de decodificar los datos.

La solución que terminé implementando fue el porcentaje de escaping de los datos codificados en Base64, y deshabilitarlo en el cliente. No es la solución más elegante, pero probablemente sea la mejor para la security.

Eso es porque iOS ahora bloquea requestes HTTP de forma pnetworkingeterminada. Tienes que volver a habilitarlo en tu info.plist.

https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33