如何从Javascript调用Objective C方法并在iOS中将数据发送回Javascript?

在iOS中,如何从UIWebView Javascript中调用Objective-C方法,并将数据发送回Javascript? 我知道这可以使用Webkit库在OS X上完成,但在iOS上可以吗? PhoneGap如何实现这一目标?

有一个API可以直接从Objective-C调用JavaScript, 但不能直接从Javascript调用Objective-C。

如何告诉你的Objective-C代码在你的WebView中使用Javascript做些什么

您必须将您的Javascript操作序列化为一个特殊的URL并在UIWebView的委托的shouldStartLoadWithRequest方法中拦截该URL。

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; 

在那里你可以反序列化这个特殊的URL并解释它在Objective-C上做你想做的事情。 (您应该在上面的shouldStartLoadWithRequest方法中返回NO ,以便UIWebView不会使用您的伪造URL实际发出HTTP请求来加载网页。)

如何从Objective-C运行Javascript代码

然后你可以通过在你的webview中调用这个方法来从Objective-C运行Javascript。

 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; 

示例代码

我build议使用伪造的URLscheme,这样就很容易区分你的动作URL和合法请求的区别。 您可以在Javascript中根据以下方式提出这个请求:

 // JavaScript to send an action to your Objective-C code var myAppName = 'myfakeappname'; var myActionType = 'myJavascriptActionType'; var myActionParameters = {}; // put extra info into a dict if you need it // (separating the actionType from parameters makes it easier to parse in ObjC.) var jsonString = (JSON.stringify(myActionParameters)); var escapedJsonParameters = escape(jsonString); var url = myAppName + '://' + myActionType + "#" + escapedJsonParameters; document.location.href = url; 

然后在UIWebView.delegateshouldStartLoadWithRequest方法中,可以检查URLscheme和片段,以检查它是一个正常请求还是您的特殊操作之一。 (URL的片段是在# 。)

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { // these need to match the values defined in your JavaScript NSString *myAppScheme = @"myfakeappname"; NSString *myActionType = @"myJavascriptActionType"; // ignore legit webview requests so they load normally if (![request.URL.scheme isEqualToString:myAppScheme]) { return YES; } // get the action from the path NSString *actionType = request.URL.host; // deserialize the request JSON NSString *jsonDictString = [request.URL.fragment stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; // look at the actionType and do whatever you want here if ([actionType isEqualToString:myActionType]) { // do something in response to your javascript action // if you used an action parameters dict, deserialize and inspect it here } // make sure to return NO so that your webview doesn't try to load your made-up URL return NO; } 

(阅读这个答案,如果你需要帮助反序列化您的JSONstring到NSDictionary。)

更改页面的位置可能会导致几个问题 :

  1. 所有setInterval和setTimeout立即停止位置更改
  2. 每个innerHTML在取消位置更改后都不起作用!
  3. 你可能会得到其他很奇怪的错误,真的很难诊断…

这里提供的解决scheme是:

继续使用相同的URL技术(在js和objective-c上),只需使用iframe更改位置:

  var iframe = document.createElement("IFRAME"); iframe.setAttribute("src", "js-frame:myObjectiveCFunction"; document.documentElement.appendChild(iframe); iframe.parentNode.removeChild(iframe); iframe = null; 

希望有所帮助

从Objective-C:你可以将一个string的JavaScript函数传递给UIWebView。 网页将执行它并返回结果。 这样你可以传递variables并从Javascript获取数据。

 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script 

例:

 NSString *script = @"document.getElementById('myTextField').value"; NSString *output = [myWebView stringByEvaluatingJavaScriptFromString:script]; 

来自Javascript:将您的数据传递到URL中。 在UIWebViewDelegate中拦截URL请求。 通过返回NO获取数据并终止URL请求。

 <script>window.location = "url://key1/value1"; </script> 

拦截URL请求

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType