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

问题描述 投票:31回答:3

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

javascript ios objective-c uiwebview
3个回答
64
投票

有一个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方面想要的目的。 (您应该在上述NO方法中返回shouldStartLoadWithRequest,以便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.delegateshouldStartLoadWithRequest方法中,您可以检查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;
}

((如果需要帮助,请阅读this answer,将json字符串反序列化为NSDictionary。)

更改页面的位置可能会导致多个issues

  1. 所有setInterval和setTimeout在位置更改后立即停止
  • 取消位置更改后,所有innerHTML都不起作用!
  • 您可能会遇到其他非常奇怪的错误,很难诊断……
  • here提供的解决方案是:

    保持使用相同的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:您可以将JavaScript函数以字符串形式传递给UIWebView。该网页将执行它并返回结果。这样,您可以传递变量并从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>
    

    Intercept the URL request

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

    12
    投票

    更改页面的位置可能会导致多个issues


    5
    投票

    来自Objective-C:您可以将JavaScript函数以字符串形式传递给UIWebView。该网页将执行它并返回结果。这样,您可以传递变量并从Javascript获取数据。

    最新问题
    © www.soinside.com 2019 - 2025. All rights reserved.