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

IT技术 javascript ios objective-c uiwebview
2021-01-16 01:46:38

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

3个回答

有一个 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 运行 Javascript 代码

然后你可以通过在你的 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;
}

如果您需要帮助将 json 字符串反序列化为 NSDictionary,请阅读此答案。)

很好的例子。从 PHP 你可以这样编码: $fragment = array("key"=>"val"); $url = 'myApp://actionType#'.rawurlencode(json_encode($fragment));
2021-03-14 01:46:38
应该 NSString *actionType = request.URL.path; 是 NSString *actionType = request.URL.host; ?
2021-03-17 01:46:38
我的意思是“myScheme://myAction#jsonEscapedParameter”中的 URL.host 应该返回myAction部分。查看文档 developer.apple.com/library/ios/documentation/cocoa/reference/...
2021-04-01 01:46:38
尽管使用大写字母发送并检查大写字母,但我还是遇到了 myAppScheme 以小写字母传递给目标 c 的问题。只是抬头
2021-04-01 01:46:38
@Colonize.bat 这种方法被广泛使用,不应该让你被拒绝。(当然,除了死亡和税收之外,生活中没有什么是确定的,但我已经这样做了五年多,没有任何问题。)
2021-04-08 01:46:38

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

  1. 所有 setInterval 和 setTimeout 立即停止位置更改
  2. 取消位置更改后,每个 innerHTML 都将无法工作!
  3. 您可能会遇到其他非常奇怪的错误,很难诊断……

此处提供的解决方案是:

继续使用相同的 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;

希望有帮助

不适用于 iOS 10 请检查我的问题stackoverflow.com/q/43867801/3378413
2021-04-01 01:46:38

从 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>

拦截URL请求

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