如何从 Javascript 调用 Objective-C 方法并将数据发送回 iOS 中的 Javascript? [英] How to invoke Objective-C method from Javascript and send back data to Javascript in iOS?

查看:30
本文介绍了如何从 Javascript 调用 Objective-C 方法并将数据发送回 iOS 中的 Javascript?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

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

如何告诉您的 Objective-C 代码从您的 WebView 中的 Javascript 执行某些操作

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

- (BOOL)webView:(UIWebView *)webViewshouldStartLoadWithRequest:(NSURLRequest *)request导航类型:(UIWebViewNavigationType)导航类型;

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

如何从 Objective-C 运行 Javascript 代码

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

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

示例代码

我建议使用虚假的 URL 方案,这样就可以轻松区分您的操作 URL 和合法请求之间的区别.您可以按照以下方式在 Javascript 中发出此请求:

//JavaScript 向你的 Objective-C 代码发送一个动作var myAppName = 'myfakeappname';var myActionType = 'myJavascriptActionType';var myActionParameters = {};//如果需要,将额外信息放入 dict//(将 actionType 与参数分开,在 ObjC 中更容易解析.)var jsonString = (JSON.stringify(myActionParameters));var escapedJsonParameters = escape(jsonString);var url = myAppName + '://' + myActionType + "#" + escapedJsonParameters;document.location.href = url;

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

- (BOOL)webView:(UIWebView *)webViewshouldStartLoadWithRequest:(NSURLRequest *)request导航类型:(UIWebViewNavigationType)导航类型{//这些需要匹配 JavaScript 中定义的值NSString *myAppScheme = @"myfakeappname";NSString *myActionType = @"myJavascriptActionType";//忽略合法的 webview 请求,以便它们正常加载如果 (![request.URL.scheme isEqualToString:myAppScheme]) {返回是;}//从路径中获取动作NSString *actionType = request.URL.host;//反序列化请求 JSONNSString *jsonDictString = [request.URL.fragment stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];//查看 actionType 并在这里做任何你想做的事if ([actionType isEqualToString:myActionType]) {//做一些事情来响应你的 javascript 动作//如果您使用了动作参数字典,请在此处反序列化并检查它}//确保返回 NO 以便您的 webview 不会尝试加载您创建的 URL返回否;}

(如果您需要有关将 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆