如何从Javascript调用Objective-C方法并将数据发送回iOS中的Javascript? [英] How to invoke Objective-C method from Javascript and send back data to Javascript in iOS?
问题描述
在iOS中,如何在UIWebView
中从Javascript调用Objective-C方法并将其发送回Java数据?我知道可以使用Webkit库在OS X上完成此操作,但是在iOS上可以吗? PhoneGap如何实现这一目标?
有一个API可直接从Objective-C调用JavaScript,但是您不能直接从Javascript调用Objective-C. >
如何告诉您的Objective-C代码通过WebView中的Java脚本执行某些操作
您必须将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运行Java代码
然后,您可以通过在Webview上调用此方法来从Objective-C运行Javascript.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
示例代码
我建议您使用伪造的URL方案,这样很容易区分您的操作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
的shouldStartLoadWithRequest
方法中,您可以检查URL方案和片段以检查它是正常请求还是特殊操作之一. (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;
}
(如果您需要帮助将json字符串反序列化为NSDictionary,请阅读此答案.)
In iOS, how can I call an Objective-C method from Javascript in a UIWebView
and have it send data back to the Javascript? I know that this could be done on OS X using the Webkit library, but is this possible on iOS? How does PhoneGap achieve this?
There is an API to call JavaScript directly from Objective-C, but you cannot call Objective-C directly from Javascript.
How to tell your Objective-C code to do something from the Javascript in your WebView
You have to serialize your Javascript action into a special URL and intercept that URL in the UIWebView's delegate's shouldStartLoadWithRequest
method.
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType;
There you can deserialize that special URL and interpret it to do what you want on the Objective-C side. (You should return NO
in the above shouldStartLoadWithRequest
method so the UIWebView doesn't use your bogus URL to actually make an HTTP request to load a webpage.)
How to Run Javascript Code from Objective-C
Then you can run Javascript from Objective-C by calling this method on your webview.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
Example Code
I recommend using a bogus URL scheme so it will be easy to tell the difference between your action URLs and legit requests. You can make this request in the Javascript along these lines:
// 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;
Then in the UIWebView.delegate
's shouldStartLoadWithRequest
method, you can inspect the URL scheme and fragment to check if it's a normal request or one of your special actions. (The fragment of a URL is what comes after the #
.)
- (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;
}
(Read this answer if you need help deserializing your json string into an NSDictionary.)
这篇关于如何从Javascript调用Objective-C方法并将数据发送回iOS中的Javascript?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!