example app ios objective-c uiwebview wkwebview

ios - app - Método delegado UIWebView shouldStartLoadWithRequest: equivalente en WKWebView?



wkwebview ios (6)

Tengo un módulo dentro de mi aplicación iOS 7+ que es un UIWebView. La página html carga un javascript que crea botones de forma personalizada (usando la biblioteca de Raphaeljs). Con UIWebView, establezco delegate en self. El método de delegado webView: shouldStartLoadWithRequest: navigationType: se webView: shouldStartLoadWithRequest: navigationType: cada vez que se presiona uno de mis botones personalizados. Las solicitudes no deberían ser manejadas por el html, sino por el código de iOS. Así que utilicé una convención de solicitud (leer en algún lugar aquí en stackoverflow) usando "inapp" como el esquema de mis solicitudes. Luego verifico por el host y tomo las medidas apropiadas.

Este código funciona bien en iOS 7. Pero las vistas web aparecen en blanco en iOS 8 (¿error?), Así que decidí usar WKWebView para dispositivos con iOS 8. Las vistas web ahora se muestran bien (¡y sorprendentemente más rápido!), Pero mis botones no tienen ningún efecto.

Intenté usar - (WKNaviation *)loadRequest:(NSURLRequest *)request , pero no fue llamado.

No puedo encontrar un equivalente directo del método delegado webView: shouldStartLoadWithRequest: navigationType: ¿Cuál es la mejor manera de manejar esas solicitudes con WKWebView?


En Swift puedes hacer algo como esto:

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) { switch navigationAction.request.URLString { case "http://action.is.needed/some-action": self.someFunc() decisionHandler(.Cancel) break default: decisionHandler(.Allow) break } }

Y este es el enlace en la página web:

<a href="http://action.is.needed/some-action">Hello world!</a>


He estado buscando una buena explicación, pero no he encontrado ninguna. He utilizado lo siguiente en mi aplicación y todo parece funcionar ( Edición: actualizada según el comentario de ccoroom ):

UIWebViewDelegate - webView:shouldStartLoadWithRequest:navigationType: WKNavigationDelegate - webView:decidePolicyForNavigationAction:decisionHandler:

Aquí están los otros métodos de UIWebViewDelegate :

UIWebViewDelegate - webViewDidStartLoad: WKNavigationDelegate - webView:didCommitNavigation: UIWebViewDelegate - webViewDidFinishLoad: WKNavigationDelegate - webView:didFinishNavigation: UIWebViewDelegate - webView:didFailLoadWithError: WKNavigationDelegate - webView:didFailNavigation:withError: - webView:didFailProvisionalNavigation:withError:

Aunque me encantaría que alguien me confirmara esto.

Editar: en realidad, he respondido la pregunta que tenías en el título (aunque ya no confío en que webView:didCommitNavigation: se llame exactamente en el mismo punto en el ciclo de vida), pero al volver a leer tu descripción parece lo que lo que realmente necesita saber es cómo volver a implementar un puente Javascript / Objective-C utilizando WKWebView. Así que eche un vistazo a mi otra respuesta.


Para responder a la pregunta original, el equivalente de webView:shouldStartLoadWithRequest:navigationType: en UIWebView es webView:decidePolicyForNavigationAction:decisionHandler: en WKWebView. Estos métodos se invocan antes de realizar cada solicitud (incluida la solicitud inicial) y brindan la posibilidad de permitir / rechazarla.


Puede agregar Observer para su WKWebView

static void* keyValueObservingContext = &keyValueObservingContext; [webView addObserver:self forKeyPath:@"URL" options:0 context:keyValueObservingContext]; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"URL"]){ // do something } }

No olvides quitarlo a la vista. Desaparecerá.

-(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [webView removeObserver:self forKeyPath:@"URL"]; }


Solo usa el siguiente método, es parte de WKNavigationDelegate

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSURLRequest *request = navigationAction.request; NSString *url = [[request URL]absoluteString]; decisionHandler(WKNavigationActionPolicyAllow); }


Volver a leer su descripción parece que lo que realmente necesita saber es cómo volver a implementar un puente JavaScript / Objective-C utilizando WKWebView.

Acabo de hacer esto yo mismo, siguiendo el tutorial en http://tetontech.wordpress.com/2014/07/17/objective-c-wkwebview-to-javascript-and-back/ y la información en http://nshipster.com/wkwebkit/

WKWebView tiene una forma integrada de comunicación entre Javascript y Objective-C / Swift: WKScriptMessageHandler .

En primer lugar, incluya los encabezados WebKit y el protocolo WKScriptMessageHandler en el encabezado de su controlador de vista:

#import <UIKit/UIKit.h> #import <WebKit/WebKit.h> @interface ViewController : UIViewController <WKScriptMessageHandler> @end

Al inicializar su WKWebView , debe configurarlo con un manejador de mensajes de script. Llámalo como quieras, pero a mí me parece que darle un nombre a tu aplicación tiene sentido.

WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init]; [theConfiguration.userContentController addScriptMessageHandler:self name:@"myApp"]; _theWebView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:theConfiguration]; [_theWebView loadRequest:request]; [self.view addSubview:_theWebView];

Ahora, implemente userContentController:didReceiveScriptMessage: Esto se dispara cuando su vista web recibe un mensaje, por lo que hace el trabajo que estaba haciendo previamente con webView:shouldStartLoadWithRequest:navigationType:

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { NSDictionary *sentData = (NSDictionary *)message.body; NSString *messageString = sentData[@"message"]; NSLog(@"Message received: %@", messageString); }

Ahora está listo para recibir mensajes de Javascript. La llamada a la función que necesita agregar a su Javascript es esta:

window.webkit.messageHandlers.myApp.postMessage({"message":"Hello there"});