在iOS中,如何在UIWebView
中从Javascript调用Objective-C方法并让它将数据发送回Javascript?我知道这可以使用Webkit库在OS X上完成,但是这可以在iOS上实现吗? PhoneGap如何实现这一目标?
答案 0 :(得分:64)
有一个API直接从Objective-C,调用JavaScript,但你无法直接从Javascript调用Objective-C。
您必须将Javascript操作序列化为特殊URL,并在UIWebView的委托shouldStartLoadWithRequest
方法中拦截该URL。
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType;
在那里,您可以反序列化该特殊URL并将其解释为在Objective-C端执行您想要的操作。 (您应该在上面的NO
方法中返回shouldStartLoadWithRequest
,这样UIWebView就不会使用您的虚假URL来实际发出加载网页的HTTP请求。)
然后,您可以通过在webview上调用此方法从Objective-C运行Javascript。
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
我建议使用伪造的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.delegate
的{{1}}方法中,您可以检查URL方案和片段,以检查它是正常请求还是您的某个特殊操作。 (URL的片段是shouldStartLoadWithRequest
之后的内容。)
#
(如果需要帮助将json字符串反序列化为NSDictionary,请阅读this answer。)
答案 1 :(得分:11)
更改网页的位置可能会导致多个issues:
提供here的解决方案是:
继续使用相同的网址技术(在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;
希望有所帮助
答案 2 :(得分:5)
从Objective-C:您可以将字符串中的javascript函数传递给UIWebView。网页将执行它并返回结果。这样您就可以传递变量并从Javascript中获取数据。
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
示例:
NSString *script = @"document.getElementById('myTextField').value";
NSString *output = [myWebView stringByEvaluatingJavaScriptFromString:script];
来自Javascript:将您的数据传递到网址中。拦截UIWebViewDelegate中的URL请求。返回NO。
获取数据并中止URL请求<script>window.location = "url://key1/value1"; </script>
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType