使用 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的主要内容,如果未能解决你的问题,请参考以下文章

AJAX XMLHttpRequest POST

原生Ajax(XMLHttpRequest)

我无法使用 AJAX (XMLHttpRequest) 获取 responseXML

使用 Ajax XMLHttpRequest 上传文件

原生Ajax--XmlHttpRequest对象

不同浏览器创建 ajax XMLHTTPRequest对象的方法及兼容性问题总结