简体   繁体   English

如何从Javascript调用Objective-C?

[英]How to call Objective-C from Javascript?

I have a WebView, and I want to call a view in Objective-C from JavaScript. 我有一个WebView,我想从JavaScript调用Objective-C中的一个视图。 Does someone know how I can do this? 有人知道我怎么做吗?


I have this code in my ViewController: 我的ViewController中有这个代码:

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

 NSString *requestString = [[request URL] absoluteString];
 NSArray *components = [requestString componentsSeparatedByString:@":"];

 if ([components count] > 1 && 
  [(NSString *)[components objectAtIndex:0] isEqualToString:@"myapp"]) {
  if([(NSString *)[components objectAtIndex:1] isEqualToString:@"myfunction"]) 
  {

   NSLog([components objectAtIndex:2]); [[Airship shared] displayStoreFront]; //<- This is the code to open the Store
   NSLog([components objectAtIndex:3]); // param2
   // Call your method in Objective-C method using the above...
  }
  return NO;
 }

 return YES; // Return YES to make sure regular navigation works as expected.
}

And in Javascript: 并在Javascript中:

function store(event)
{
    document.location = "myapp:" + "myfunction:" + param1 + ":" + param2;
}

But nothing happens. 但没有任何反应。

The standard workaround for UIWebView is to set a UIWebViewDelegate , and implement the method webView:shouldStartLoadWithRequest:navigationType: . UIWebView的标准解决方法是设置UIWebViewDelegate ,并实现webView:shouldStartLoadWithRequest:navigationType:方法webView:shouldStartLoadWithRequest:navigationType: . In your JavaScript code, navigate to some fake URL that encodes the information you want to pass to your app, like, say: 在您的JavaScript代码中,导航到一些伪造的URL,该URL会对您要传递给应用的信息进行编码,例如:

window.location = "fake://myApp/something_happened:param1:param2:param3";

In your delegate method, look for these fake URLs, extract the information you need, take whatever action is appropriate, and return NO to cancel the navigation. 在您的委托方法中,查找这些虚假URL,提取您需要的信息,采取适当的操作,并返回NO以取消导航。 It's probably best if you defer any lengthy processing using some flavor of performSelector . 如果你使用一些performSelector味道推迟任何冗长的处理,这可能是最好的。

The window.location method of calling objective c from JS isn't recommended. 不建议从JS调用目标c的window.location方法。 One example of problems: if you make two immediate consecutive calls one is ignored (since you can't change location too quickly) - try it yourself.. 问题的一个例子:如果你进行两次立即连续调用,则忽略一次(因为你不能太快地改变位置) - 自己尝试一下..

I recommend the following alternative approach: 我推荐以下替代方法:

function execute(url) 
{
  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", url);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;
}

You call the execute function repeatedly and since each call executes in its own iframe, they should not be ignored when called quickly. 您重复调用execute函数,因为每个调用都在自己的iframe中执行,所以在快速调用时不应忽略它们。

Credits to this guy . 这个家伙的功劳。

Obliviux, Obliviux,

Your code seems to be perfect. 你的代码似乎很完美。

The reason for the problem is that you must have missed to map the delegate. 问题的原因是你必须错过映射代表。

Either

  1. Connect the delegate of the webView to the file owner in the .xib file 将webView的委托连接到.xib文件中的文件所有者

or 要么

  1. Use webView.delegate = self; 使用webView.delegate = self;

in your viewDidLoad . 在你的viewDidLoad

Thanks 谢谢

Like people said here, you have to use the method webView:shouldStartLoadWithRequest:navigationType: from the UIWebviewDelegate. 就像人们在这里说的那样,你必须使用webView:shouldStartLoadWithRequest:navigationType:来自UIWebviewDelegate。

This api http://code.google.com/p/jsbridge-to-cocoa/ does it for you. 这个api http://code.google.com/p/jsbridge-to-cocoa/为您做到了。 It is very lightweight. 它非常轻巧。 You can pass images, strings and arrays from javascript to objective-C. 您可以将图像,字符串和数组从javascript传递到objective-C。

I had an issue with this approach: I wanted to send several messages to the iphone device, but it seemed that they were "overlaped" as they could not process all of them sequentially. 我对这种方法有一个问题:我想向iphone设备发送几条消息,但似乎它们被“重叠”,因为它们无法顺序处理所有这些消息。

Example: when executing this code: 示例:执行此代码时:

window.location = "app://action/foo";
window.location = "app://action/bar";

The action foo was never executed. 动作foo从未执行过。

What I had to do was the following: 我必须做的是以下内容:

waitingForMessage = false;

function MsgProcessed(){
    waitingForMessage = false;
}

function SyncLaunchURL(url){
    if (waitingForMessage){
        setTimeout(function(){SyncLaunchURL(url)},100);
    }else{
        window.location = url
        waitingForMessage = true;   
    }
}

SyncLaunchURL("app://action/foo");
SyncLaunchURL("app://action/bar");

With this approach, the iphone has to call MsgProcessed() after processing the call. 使用这种方法,iphone必须在处理呼叫后调用MsgProcessed()。 This way works for me, and maybe helps someone with the same problem! 这种方式适合我,也许可以帮助有同样问题的人!

Check this one - understanding XMLHttpRequest responses using this (or other javascript) functions? 检查一下 - 使用此(或其他javascript)函数了解XMLHttpRequest响应? , it's using objective C to call ajax js function, and get the response after it's done, you know the trick is that webview will be triggered when you change the location in javascript, so you can check the location to know its your javascript call or the real request. ,它使用目标C来调用ajax js函数,并在完成后得到响应,你知道诀窍是当你在javascript中更改位置时会触发webview,这样你就可以检查位置以了解你的javascript调用或真正的要求。

Assuming you're doing an app, you can look at how PhoneGap implements that (or even use it). 假设你正在做一个应用程序,你可以看看PhoneGap如何实现它(甚至使用它)。 It's a library that supports back-and-forth communication between JS and OBJ-C. 它是一个支持JS和OBJ-C之间来回通信的库。 There are other libraries and solutions, as well. 还有其他库和解决方案。

If you're talking about a web app (something the user gets to from Mobile Safari), you can't get to Objective-C from there. 如果您正在谈论一个Web应用程序(用户从Mobile Safari获得的东西),那么您无法从那里获得Objective-C。

Although this is a very old question now, it keeps getting returned by Google and there is a good answer now: the WebScripting informal protocol. 虽然现在这是一个非常古老的问题,但谷歌一直在回归,现在有一个很好的答案:WebScripting非正式协议。 It allows you to expose an objective C object to Javascript. 它允许您将目标C对象公开给Javascript。

http://developer.apple.com/library/safari/documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html#//apple_ref/doc/uid/30001215-BBCBFJCD http://developer.apple.com/library/safari/documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html#//apple_ref/doc/uid/30001215-BBCBFJCD

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM