iOS JavaScript桥

and*_*111 99 javascript html5 uiwebview ios

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

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

小智 149

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

-

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

1.从Objective-C执行JS方法

这只是一行代码.

NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"your javascript code string here"];
Run Code Online (Sandbox Code Playgroud)

有关官方UIWebView文档的更多详细信息.

2.从JS执行Objective-C方法

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

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

window.location = yourscheme://callfunction/parameter1/parameter2?parameter3=value
Run Code Online (Sandbox Code Playgroud)

并使用以下方法从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
   } 
}
Run Code Online (Sandbox Code Playgroud)

这不是它应该是干净的(或通过使用windowScriptObject),但它的工作原理.

3.从Objective-C收听本机JS事件(例如DOM ready事件)

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

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

  • 提示:不要在您的方案中加入下划线或类似内容. (12认同)
  • 当你应该:)时返回一个值 (4认同)
  • 另一个提示:在iFrame中加载URL以防止闪烁 (2认同)

tal*_*kol 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;
}
Run Code Online (Sandbox Code Playgroud)

execute重复调用该函数,并且由于每个调用都在其自己的iframe中执行,因此在快速调用时不应忽略它们.

这个家伙的功劳.

  • 更喜欢这个人的信用:) http://stackoverflow.com/a/2935005/172361 (12认同)

Jos*_*nox 12

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

另一种可能会让您从应用商店中被拒绝的替代方法是使用WebScriptObject.

这些API在OSX上是公开的,但不在iOS上.

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

@interface WebScriptObject: NSObject
@end

@interface WebView
- (WebScriptObject *)windowScriptObject;
@end

@interface UIWebDocumentView: UIView
- (WebView *)webView;
@end
Run Code Online (Sandbox Code Playgroud)

您需要定义将用作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
Run Code Online (Sandbox Code Playgroud)

现在将实例设置为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"];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

yourBridge.someEvent(100, "hello");
yourBridge.testfoo();
Run Code Online (Sandbox Code Playgroud)


Ale*_*one 5

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