UIWebViewDelegate不会监控使用XMLHttpRequest发出的请求,这是真的吗?如果是这样的话,有没有办法监控这类请求?
例如,UIWebViewDelegate在-(BOOL) webView:(UIWebView *)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();发布于 2011-04-21 10:03:29
这个问题很有趣。
要实现这一点,需要两个部分: JavaScript处理程序和UIWebView委托方法。在JavaScript中,我们可以修改原型方法以在创建AJAX请求时触发事件。使用我们的UIWebView委托,我们可以捕获这些事件。
JavaScript处理程序
当发出AJAX请求时,我们需要得到通知。我找到了解决方案here。
在我们的例子中,为了让代码正常工作,我将下面的JavaScript放在一个名为ajax_handler.js的资源中,该资源与我的应用程序捆绑在一起。
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();
}这实际上是将浏览器的位置更改为某种虚构的URL方案(在本例中为mpAjaxHandle),其中包含有关所发出的请求的信息。不要担心,我们的代理使用catch this,位置不会改变。
UIWebView委派
首先,我们需要读取JavaScript文件。我建议将其存储在静态变量中。我有使用+初始化的习惯。
static NSString *JSHandler;
+ (void)initialize {
JSHandler = [[NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"ajax_handler" withExtension:@"js"] encoding:NSUTF8StringEncoding error:nil] retain];
}接下来,我们希望在页面加载完成之前注入这个JavaScript,这样我们就可以接收所有事件。
- (void)webViewDidStartLoad:(UIWebView *)webView {
[webView stringByEvaluatingJavaScriptFromString:JSHandler];
}最后,我们想要捕获事件。
由于URL方案是虚构的,我们不想实际遵循它。我们返回,没有,一切都很好。
#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;
}我使用该解决方案创建了一个示例项目,但没有地方托管它。你可以给我发消息,如果你可以托管它,我会相应地编辑这篇文章。
发布于 2012-07-24 12:56:22
您可以使用NSURLProtocol。例如,如果您使用http://localhost/path调用XMLHttpRequest,您可以使用以下方法来处理它:
@interface YourProtocol: NSURLProtocol然后,对于实现:
+ (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
{
}您需要按如下方式注册协议:
[NSURLProtocol registerClass:[YourProtocol class]];发布于 2012-01-31 17:53:06
通过实现和注册NSURLProtocol的子类,您可以捕获来自UIWebView的所有请求。在某些情况下,这可能是过度杀伤力,但如果您不能修改实际运行的javascript,那么它是您最好的选择。
在我的例子中,我需要捕获所有请求,并向每个请求插入一个特定的HTTP头。我已经实现了NSURLProtocol,使用registerClass注册它,如果请求对应于我感兴趣的URL,则在我的子类中对+ (BOOL)canInitWithRequest:(NSURLRequest *)请求回答YES。然后,您必须实现协议的其他方法这可以通过使用NSURLConnection、将协议类设置为委托并将NSURLConnection的委托方法重定向到NSURLProtocolClient来实现
https://stackoverflow.com/questions/5353278
复制相似问题