如何从Javascript调用Objective-C?

问题描述 投票:41回答:8

我有一个WebView,我想从JavaScript调用Objective-C中的一个视图。有人知道我怎么做吗?


我的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.
}

并在Javascript中:

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

但没有任何反应。

iphone cocoa-touch uiwebview
8个回答
52
投票

UIWebView的标准解决方法是设置UIWebViewDelegate,并实现方法webView:shouldStartLoadWithRequest:navigationType:。在您的JavaScript代码中,导航到一些伪造的URL,该URL会对您要传递给应用的信息进行编码,例如:

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

在您的委托方法中,查找这些虚假URL,提取您需要的信息,采取适当的操作,并返回NO以取消导航。如果你推迟使用some flavor of performSelector进行任何冗长的处理,这可能是最好的。


32
投票

不建议从JS调用目标c的window.location方法。问题的一个例子:如果你进行两次立即连续调用,则忽略一次(因为你不能太快地改变位置) - 自己尝试一下..

我推荐以下替代方法:

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

你反复调用execute函数,因为每个调用都在自己的iframe中执行,所以在快速调用时不应忽略它们。

积分兑换this guy


4
投票

Obliviux,

你的代码似乎很完美。

问题的原因是你必须错过映射代表。

  1. 将webView的委托连接到.xib文件中的文件所有者

要么

  1. 使用webView.delegate = self;

在你的viewDidLoad

谢谢


3
投票

就像人们在这里所说的那样,你必须使用webView:shouldStartLoadWithRequest:navigationType:来自UIWebviewDelegate。

这个api http://code.google.com/p/jsbridge-to-cocoa/为你做。它非常轻巧。您可以将图像,字符串和数组从javascript传递到objective-C。


2
投票

我对这种方法有一个问题:我想向iphone设备发送几条消息,但似乎它们被“重叠”,因为它们无法顺序处理所有这些消息。

示例:执行此代码时:

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

行动foo从未被执行过。

我必须做的是以下内容:

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");

使用这种方法,iphone必须在处理呼叫后调用MsgProcessed()。这种方式适合我,也许可以帮助有同样问题的人!


1
投票

假设你正在做一个应用程序,你可以看看PhoneGap如何实现它(甚至使用它)。它是一个支持JS和OBJ-C之间来回通信的库。还有其他库和解决方案。

如果您正在谈论一个Web应用程序(用户从Mobile Safari获得的东西),那么您无法从那里获得Objective-C。


1
投票

检查一下 - understanding XMLHttpRequest responses using this (or other javascript) functions?,它使用目标C调用ajax js函数,并在完成后得到响应,你知道诀窍是当你在javascript中更改位置时会触发webview,所以你可以检查位置知道它是您的JavaScript调用或真实请求。


0
投票

虽然现在这是一个非常古老的问题,但谷歌一直在回归,现在有一个很好的答案:WebScripting非正式协议。它允许您将目标C对象公开给Javascript。

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

© www.soinside.com 2019 - 2024. All rights reserved.