使用 AJAX/XMLHttpRequest 时不调用 shouldStartLoadWithRequest
Posted
技术标签:
【中文标题】使用 AJAX/XMLHttpRequest 时不调用 shouldStartLoadWithRequest【英文标题】:shouldStartLoadWithRequest is not called when using AJAX/XMLHttpRequest 【发布时间】:2010-04-25 11:03:39 【问题描述】:我正在尝试将方法调用从 javascript 发送到 Objective-C,反之亦然。一切都适用于 window.location 触发的 url,它们被 shouldStartLoadWithRequest 捕获。现在,如果我尝试改用 AJAX 调用,则不会调用 shouldStartLoadWithRequest。 有没有办法做到这一点?主要是我不想被限制在可以从 JavaScript 传递到 Objective-C 的数据的最大 URL 大小。
我的 UIWebViewDelegate 实现:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
NSString *url = [[request URL] absoluteString];
NSRange urlrange = [url rangeOfString:@"myScheme://"];
if(urlrange.length > 0)
NSLog(@"this is an objective-c call, do not load link: %@", [url substringWithRange:NSMakeRange(urlrange.location, [url length])] );
return NO;
else
NSLog(@"not an objective-c call, load link: ", url );
return YES;
我的 JavaScript 调用:
// works
window.location.href = "myScheme://readyHref";
// fails
var xmlHttpReq = false;
if (window.XMLHttpRequest)
xmlHttpReq = new XMLHttpRequest();
else if (window.ActiveXObject)
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
xmlHttpReq.open('GET', "myScheme://readyAJAX", false);
xmlHttpReq.send();
【问题讨论】:
【参考方案1】:如果您希望以更简洁的方式将数据从 JavaScript 传输到 Objective-C,您可以按照以下步骤操作:
-
一旦你有 JS 数据你想发送回 Objective-C 然后在 JS 中将它存储在一些全局可访问的变量中,例如
var myTempData = ...
使用document.location = 'myapp://fire-some-event'
的上述技术
在您的 Objective-C 代码中执行 [myWebView stringByEvaluatingJavaScriptFromString:@"myTempData"]
。
我想你已经完成了,注意 threading/object-to-string-via-json-encoding。
【讨论】:
【参考方案2】:虽然我找不到为什么 AJAX 请求不被 shouldStartLoadWithRequest 拦截的答案,但我找到了两种解决方法。我假设 JavaScript 请求没有被拦截,但只有与 html 相关的/发起的请求被拦截。如果有人可以验证或更正这一点,我会很高兴。
这两种解决方法很简单。一方面,URL 中 256 个字符的限制似乎不会影响 MobileSafari,或者至少不会影响该状态下的 url。我读到了Safari allows 80'000 charcters。但是,我对此感觉并不好。所以解决方法 #2 是使用一个使用 POST 方法的 html 表单并将操作设置为您的方案。数据可以以输入字段的值等形式存储。使用 JavaScript 提交表单后,将触发 shouldStartLoadWithRequest 并且可以从 HTTPBody 检索数据。
【讨论】:
【参考方案3】:我不确定这是否适合您,但如果您尝试使用 shouldStartLoadWithRequest 以便从 javascript 访问本机电话功能,您可以使用 PhoneGap。它是一个方便的开源 Objective-c 框架,能够桥接 javascript 和 Objective-c。
我需要一种通过 javascript 异步使手机振动的方法,我查看了 PhoneGap 源代码以了解他们是如何做到的。经过一些测试,我发现 $.ajax 不会被 shouldStartLoadWithRequest 拦截,而且它对何时拦截 http 请求非常特别。您可以通过调用 document.location 而不是 $.ajax 并使用另一个协议(例如 gap:// 而不是 http://)来使一切正常运行。
所以 javascript 代码看起来像:document.location = "gap://vibrate";
以及objective-c代码:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType NSURL *url = request.URL; NSString *urlString = url.relativeString; if ([urlString isEqualToString:@"gap://vibrate"]) AudioservicesPlaySystemSound(kSystemSoundID_Vibrate); ; 返回是;
【讨论】:
以上是关于使用 AJAX/XMLHttpRequest 时不调用 shouldStartLoadWithRequest的主要内容,如果未能解决你的问题,请参考以下文章