首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >iOS JavaScript桥

iOS JavaScript桥
EN

Stack Overflow用户
提问于 2012-02-28 06:45:42
回答 8查看 111.4K关注 0票数 104

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

  1. 执行Objective-C
  2. Execute Objective-C中的JS方法JS
  3. 侦听Objective-C中的本机JS事件(例如DOM就绪事件)
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-02-28 07:18:13

有几个库,但我没有在大型项目中使用它们中的任何一个,所以您可能想要尝试一下:

-

然而,我认为这是足够简单的东西,你可以自己试一试。我个人就是在需要的时候这么做的。您还可以创建一个简单的库来满足您的需求。

1.从Objective-C执行JS方法

这只是一行代码。

代码语言:javascript
复制
NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"your javascript code string here"];

有关官方UIWebView Documentation的更多详细信息。

2.从JS执行Objective-C方法

不幸的是,这要稍微复杂一些,因为Mac上没有相同的windowScriptObject属性(和类)来实现两者之间的完全通信。

但是,您可以很容易地从javascript自定义URL调用,例如:

代码语言:javascript
复制
window.location = yourscheme://callfunction/parameter1/parameter2?parameter3=value

并从Objective-C截取它,如下:

代码语言:javascript
复制
- (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就绪事件)

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

再说一次,它不像应该的那样干净,但它是有效的。

票数 153
EN

Stack Overflow用户

发布于 2012-11-01 19:51:26

不推荐在接受的答案中从JS调用objective c的建议方法。问题的一个例子:如果您立即连续进行两个调用,其中一个将被忽略(您不能太快地更改位置)。

我推荐以下替代方法:

代码语言:javascript
复制
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

票数 57
EN

Stack Overflow用户

发布于 2013-09-13 01:05:31

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

另一种选择,可能会让你被应用商店拒绝,那就是使用WebScriptObject。

这些API在OSX上是公共的,但在iOS上不是。

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

代码语言:javascript
复制
@interface WebScriptObject: NSObject
@end

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

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

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

代码语言:javascript
复制
@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

代码语言:javascript
复制
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中,你可以调用:

代码语言:javascript
复制
yourBridge.someEvent(100, "hello");
yourBridge.testfoo();
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9473582

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档