54 votes

UIWebViewDelegate ne surveille pas XMLHttpRequest?

Est-il vrai que UIWebViewDelegate ne surveille pas les demandes effectuées à l'aide de XMLHttpRequest? Si oui, existe-t-il un moyen de surveiller ce type de demande?

Par exemple, UIWebViewDelegate ne détecte pas cela en -(BOOL) webView:(KMWebView *)webView shouldStartLoadWithRequest:(NSMutableURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType ;

 var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.google.com", true);

xhr.onreadystatechange=function() 
{
    if (xhr.readyState==4) 
    {
        alert(xhr.responseText);
    }
}

xhr.send();
 

80voto

Mike Pulaski Points 739

Question intéressante.

Il y a deux parties à faire ce travail: un JavaScript gestionnaire et UIWebView délégué méthodes. En JavaScript, nous pouvons modifier le prototype des méthodes pour déclencher des événements lorsqu'une requête AJAX est créé. Avec notre UIWebView délégué, nous pouvons saisir ces événements.

JavaScript Gestionnaire

Nous avons besoin d'être averti lorsqu'une requête AJAX est faite. J'ai trouvé la solution ici.

Dans notre cas, pour rendre le code du travail, j'ai mis le code JavaScript suivant dans une ressource appelée ajax_handler.js ce qui est fournie avec mon application.

var s_ajaxListener = new Object();
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
    window.location='mpAjaxHandler://' + this.url;
};

XMLHttpRequest.prototype.open = function(a,b) {
  if (!a) var a='';
  if (!b) var b='';
  s_ajaxListener.tempOpen.apply(this, arguments);
  s_ajaxListener.method = a;  
  s_ajaxListener.url = b;
  if (a.toLowerCase() == 'get') {
    s_ajaxListener.data = b.split('?');
    s_ajaxListener.data = s_ajaxListener.data[1];
  }
}

XMLHttpRequest.prototype.send = function(a,b) {
  if (!a) var a='';
  if (!b) var b='';
  s_ajaxListener.tempSend.apply(this, arguments);
  if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
  s_ajaxListener.callback();
}

Ce que cela va réellement faire est de changer l'emplacement du navigateur pour certains composée schéma d'URL (dans ce cas, mpAjaxHandle) avec des informations sur la demande. Ne vous inquiétez pas, notre délégué à l'intercepter et l'emplacement ne change pas.

UIWebView Délégué

Tout d'abord, nous avons besoin de lire notre fichier JavaScript. Je suggère de faire le stocker dans une variable statique. Je suis dans l'habitude de l'utiliser +initialiser.

static NSString *JSHandler;

+ (void)initialize {
    JSHandler = [[NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"ajax_handler" withExtension:@"js"] encoding:NSUTF8StringEncoding error:nil] retain];
}

Ensuite, nous voulons injecter ce JavaScript avant qu'une page est fait, le chargement afin que nous puissions recevoir tous les événements.

- (void)webViewDidStartLoad:(UIWebView *)webView {
    [webView stringByEvaluatingJavaScriptFromString:JSHandler];
}

Enfin, nous voulons capturer l'événement.

Depuis le Schéma d'URL est composée, nous n'avons pas vraiment envie de le suivre. Nous revenons PAS et tout est bien.

#define CocoaJSHandler          @"mpAjaxHandler"

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    if ([[[request URL] scheme] isEqual:CocoaJSHandler]) {
        NSString *requestedURLString = [[[request URL] absoluteString] substringFromIndex:[CocoaJSHandler length] + 3];

        NSLog(@"ajax request: %@", requestedURLString);
        return NO;
    }

    return YES;
}

J'ai créé un exemple de projet avec la solution, mais n'ont pas d'endroit pour l'accueillir. Vous pouvez moi un message si vous pouvez l'héberger et je vais éditer ce post en conséquence.

20voto

George Points 942

Vous pouvez utiliser un protocole NSURL. Par exemple, si vous appelez XMLHttpRequest avec http://localhost/path vous pouvez le gérer avec les éléments suivants:

 @interface YourProtocol: NSURLProtocol
 

Ensuite pour la mise en œuvre:

 + (BOOL)canInitWithRequest:(NSURLRequest *)request 
{
    return [request.URL.host isEqualToString:@"localhost"];
}

+ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request
{
    return request;
}

- (void) startLoading
{
    // Here you handle self.request 
}

- (void)stopLoading
{
}
 

Vous devez enregistrer le protocole comme suit:

     [NSURLProtocol registerClass:[YourProtocol class]];
 

3voto

terrinecold Points 149

Par la mise en œuvre et l'enregistrement d'une sous-classe de NSURLProtocol vous pouvez capturer toutes les demande à partir de votre UIWebView. Il est peut-être exagéré, dans certains cas, mais si vous n'êtes pas en mesure de modifier le javascript effectivement en cours d'exécution est votre meilleur pari.

Dans mon cas, j'ai besoin de saisir toutes les demande et insérer un spécifique en-tête HTTP pour chacun d'entre eux. Je l'ai fait par la mise en œuvre de NSURLProtocol, l'enregistrer à l'aide de registerClass et de répondre OUI dans mon sous-classe + (BOOL)canInitWithRequest:(NSURLRequest *)demande si la requête correspond à l'Url qui m'intéressent. Ensuite, vous aurez à mettre en œuvre les autres méthodes du protocole, ce qui peut être fait en utilisant un NSURLConnection, la définition de la classe de protocole en tant que délégué et de rediriger le délégué des méthodes de NSURLConnection à NSURLProtocolClient

1voto

Anomie Points 43759

Cela semble être vrai. Il n'y a aucun moyen de surveiller ce que fait UIWebView au-delà de ce que fournit UIWebViewDelegate, à moins que vous ne trouviez peut-être une façon d'utiliser stringByEvaluatingJavaScriptFromString: pour injecter du code Javascript afin de faire ce dont vous avez besoin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X