有趣的问题。
有两个部分可以完成这项工作: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),其中包含有关所发出请求的信息。不用担心,我们的代表抓住了这个,位置不会改变。
UIWebView 委托
首先,我们需要读取我们的 JavaScript 文件。我建议将其存储在静态变量中。我有使用 +initialize 的习惯。
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 Scheme 是组成的,我们不想真正遵循它。我们返回 NO,一切都很好。
#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;
}
我使用该解决方案创建了一个示例项目,但无处托管它。如果你能主持,你可以给我发消息,我会相应地编辑这篇文章。