iOS JavaScript桥梁

我正在开发一个应用程序,在这个应用程序中我将同时使用UIWebView中的HTML5和本机iOS框架。 我知道我可以实现JavaScript和Objective-C之间的通信。 有没有任何图书馆简化实施这种沟通? 我知道有几个库可以在HTML5和JavaScript(例如AppMobi,PhoneGap)中创build本机iOS应用程序,但我不确定是否有一个库可以帮助创build具有JavaScript使用量的本机iOS应用程序。 我需要:

  1. 从Objective-C执行JS方法
  2. 从JS执行Objective-C方法
  3. 听从Objective-C的本地JS事件(例如DOM就绪事件)

有几个图书馆,但是我没有在大型项目中使用这些图书馆,所以你可能想试试它们:

  • WebViewJavascriptBridge: https : //github.com/marcuswestin/WebViewJavascriptBridge
  • GAJavaScript: https : //github.com/newyankeecodeshop/GAJavaScript

不过,我觉得这很简单,你可以试一试。 当我需要的时候,我亲自做了这个。 您也可以创build一个适合您需求的简单库。

1.从Objective-C执行JS方法

这实际上只是一行代码。

NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"your javascript code string here"]; 

关于官方UIWebView文档的更多细节。

2.从JS执行Objective-C方法

不幸的是,这稍微复杂一点,因为Mac OSX上不存在相同的windowScriptObject属性(和类),允许在两者之间进行完整的通信。

不过,您可以轻松地从JavaScript定制的URL调用,如:

 window.location = yourscheme://callfunction/parameter1/parameter2?parameter3=value 

从Objective-C中截取它:

 - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *URL = [request URL]; if ([[URL scheme] isEqualToString:@"yourscheme"]) { // parse the rest of the URL object and execute functions } } 

这并不像应该的那样干净(或者使用windowScriptObject),但是它可以工作。

3.听从Objective-C的本地JS事件(例如DOM就绪事件)

从上面的解释可以看出,如果你想这样做,你必须创build一些JavaScript代码,将它附加到你想要监视的事件,并调用正确的window.location调用来被拦截。

再次,不应该干净,但它的工作原理。

不build议在接受的答案中从JS调用Objective C的build议方法。 问题的一个例子:如果你连续两次打电话,一个会被忽略(你不能快速改变位置)。

我推荐以下替代方法:

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

您可以反复调用execute函数,并且由于每个调用都在其自己的iframe中执行,所以在快速调用时不应忽略它们。

感谢这个家伙 。

更新:这已在iOS 8中更改。我的答案适用于以前的版本。

另一种可能会让你从app store被拒绝的方法是使用WebScriptObject。

这些API在OSX上公开,但不在iOS上。

您需要定义内部类的接口。

 @interface WebScriptObject: NSObject @end @interface WebView - (WebScriptObject *)windowScriptObject; @end @interface UIWebDocumentView: UIView - (WebView *)webView; @end 

您需要定义将用作WebScriptObject的对象

 @interface WebScriptBridge: NSObject - (void)someEvent: (uint64_t)foo :(NSString *)bar; - (void)testfoo; + (BOOL)isKeyExcludedFromWebScript:(const char *)name; + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector; + (WebScriptBridge*)getWebScriptBridge; @end static WebScriptBridge *gWebScriptBridge = nil; @implementation WebScriptBridge - (void)someEvent: (uint64_t)foo :(NSString *)bar { NSLog(bar); } -(void)testfoo { NSLog(@"testfoo!"); } + (BOOL)isKeyExcludedFromWebScript:(const char *)name; { return NO; } + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector; { return NO; } + (NSString *)webScriptNameForSelector:(SEL)sel { // Naming rules can be found at: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/WebKit/Protocols/WebScripting_Protocol/Reference/Reference.html if (sel == @selector(testfoo)) return @"testfoo"; if (sel == @selector(someEvent::)) return @"someEvent"; return nil; } + (WebScriptBridge*)getWebScriptBridge { if (gWebScriptBridge == nil) gWebScriptBridge = [WebScriptBridge new]; return gWebScriptBridge; } @end 

现在将该实例设置为您的UIWebView

 if ([uiWebView.subviews count] > 0) { UIView *scrollView = uiWebView.subviews[0]; for (UIView *childView in scrollView.subviews) { if ([childView isKindOfClass:[UIWebDocumentView class]]) { UIWebDocumentView *documentView = (UIWebDocumentView *)childView; WebScriptObject *wso = documentView.webView.windowScriptObject; [wso setValue:[WebScriptBridge getWebScriptBridge] forKey:@"yourBridge"]; } } } 

现在你的javascript里面可以调用:

 yourBridge.someEvent(100, "hello"); yourBridge.testfoo(); 

在iOS8中,您可以查看WKWebView而不是UIWebView 。 它具有以下类:WKScriptMessageHandler:提供了一种从网页中运行的JavaScript接收消息的方法。

你最好的select是Appcelerators Titanium产品。 他们已经使用webkit使用的V8引擎 JavascriptCore引擎构build了一个Obj-C javascript桥接器。 它也是开源的,所以你可以随意下载和修改Obj-C。

看看KirinJS项目: 麒麟JS允许使用Javascript的应用程序逻辑和本地用户界面足以运行的平台。

我创build了一个类似于WebViewJavascriptBridge的库,但它更像JQuery,更容易设置,更易于使用。 不依赖于jQuery(尽pipe值得称道,在我写这本书之前我已经知道了WebViewJavascriptBridge的存在),我可能刚刚在潜水之前稍微阻挡了一下。 让我知道你的想法! jockeyjs

如果您在iOS 8上使用WKWebView,请查看XWebView ,它可以自动将本机界面公开给JavaScript。