iOS JavaScript桥

时间:2012-02-27 22:45:42

标签: javascript ios html5 uiwebview

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

  1. 从Objective-C
  2. 执行JS方法
  3. 执行JS的Objective-C方法
  4. 收听来自Objective-C的本机JS事件(例如DOM ready事件)

9 个答案:

答案 0 :(得分:149)

有一些库,但我没有在大项目中使用过这些库,所以你可能想尝试一下:

-

但是,我觉得这很简单,你可以自己尝试一下。当我需要这样做时,我个人就是这样做的。您也可以创建一个适合您需求的简单库。

1。从Objective-C

执行JS方法

这只是一行代码。

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

有关官方UIWebView Documentation的更多详情。

2。从JS <​​/ h3>执行Objective-C方法

遗憾的是,这有点复杂,因为Mac OSX上不存在相同的windowScriptObject属性(和类),允许两者之间完全通信。

但是,您可以通过javascript自定义网址轻松调用,例如:

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 ready事件)

从上面的解释中,您可以看到,如果您想这样做,您必须创建一些JavaScript代码,将其附加到您要监控的事件并调用正确的window.location调用然后被截获。

同样,不应该干净,但它确实有效。

答案 1 :(得分:57)

建议不要在接受的答案中使用JS调用目标c的建议方法。问题的一个例子:如果你进行两次即时连续调用,则会忽略一次(你不能太快改变位置)。

我建议采用以下替代方法:

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的信用。

答案 2 :(得分:12)

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

可能会让您从应用商店中被拒绝的替代方法是使用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();

答案 3 :(得分:5)

In iOS8 you can look at WKWebView instead of UIWebView。这有以下几类: WKScriptMessageHandler:提供从网页中运行的JavaScript接收消息的方法。

答案 4 :(得分:3)

这可以通过iOS7,结帐http://blog.bignerdranch.com/3784-javascriptcore-and-ios-7/

来实现

答案 5 :(得分:0)

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

答案 6 :(得分:0)

查看KirinJS项目:Kirin JS,它允许使用Javascript作为应用程序逻辑和本机UI,足以运行它所运行的平台。

答案 7 :(得分:0)

我创建了一个类似WebViewJavascriptBridge的库,但它更像JQuery,更容易设置并且更易于使用。不依赖于jQuery(尽管如此,如果我在写这篇文章之前知道WebViewJavascriptBridge存在,我可能会在潜入之前稍微停下来)。让我知道你的想法! jockeyjs

答案 8 :(得分:0)

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