iOS JavaScript bridge
iOS JavaScript bridge
我正在开发一个应用程序,在该应用程序中,我将同时使用UIWebView中的HTML5和本机iOS框架。我知道我可以实现JavaScript和Objective-C之间的通信。有没有任何库可以简化这种通信的实现?我知道有几个库可以用HTML5和javascript创建原生iOS应用程序(例如AppMobi、PhoneGap),但我不确定是否有库可以帮助创建大量使用javascript的原生iOS应用。我需要:
- 从Objective-C执行JS方法
- 从JS执行Objective-C方法
- 监听Objective-C中的本地JS事件(例如DOM就绪事件)
有一些库,但我在大型项目中没有使用过它们,所以你可能想试用一下:
- WebViewJavascriptBridge:https://github.com/marcuswestin/WebViewJavascriptBridge
- GAJavaScript:https://github.com/newyankeecodeshop/GAJavaScript
--
然而,我认为这很简单,你可以自己尝试一下。当我需要这样做的时候,我个人就这样做了。您也可以创建一个简单的库来满足您的需求。
1.从Objective-C执行JS方法
这实际上只是一行代码。
NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"your javascript code string here"];
有关UIWebView官方文档的更多详细信息。
2.从JS执行Objective-C方法
不幸的是,这稍微复杂一点,因为MacOSX上没有相同的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就绪事件)
从上面的解释中,您可以看到,如果要做到这一点,您必须创建一些JavaScript代码,将其附加到要监视的事件,并调用正确的window.location
调用,然后进行拦截。
再说一次,虽然它不应该是干净的,但它是有效的。
不推荐在接受的答案中从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中执行,因此在快速调用时不应忽略它们。
归功于这个家伙。
更新:这在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();
在iOS8中,您可以查看WKWebView而不是UIWebView。它具有以下类别:WKScriptMessageHandler:提供一种从网页中运行的JavaScript接收消息的方法。
这在iOS7中是可能的,请检查http://blog.bignerdranch.com/3784-javascriptcore-and-ios-7/
您的最佳选择是Appcelerators Titanium产品。他们已经使用webkit使用的V8引擎JavascriptCore引擎构建了一个Obj-C javascript桥。它也是开源的,所以你可以下载它,并根据自己的喜好修改Obj-C。
看看KirinJS项目:KirinJS允许将Javascript用于应用程序逻辑和原生UI,足以满足其运行的平台。
我创建了一个类似WebViewJavascriptBridge的库,但它更像JQuery,更容易设置,也更容易使用。不依赖jQuery(尽管值得称赞的是,如果我在写这篇文章之前就知道WebViewJavascriptBridge的存在,我可能只是在深入研究之前稍微犹豫了一下)。让我知道你的想法!jodgejs
如果您在iOS 8上使用WKWebView,请查看XWebView,它可以自动向javascript公开本机接口。
- 为什么不't Javascript对我的输入值进行了一些重新检查
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 将函数的上下文应用于javascript变量
- 使用php或javascript从facebook相册URL中删除多余的部分
- 正在添加'X'按钮,在文本字段旁边使用javascript
- 如何在JavaScript中将字符串转换为函数引用
- 模糊事件的Javascript测试
- Javascript更改图标
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- 如何使用WCF服务和javascript表单post上传.doc文件
- javascript结合了数组和字典
- 这是什么 ==- javascript 运算符
- 从javascript创建一个列表
- 无法在通过jQuery的ajax加载的页面中执行javascript
- Javascript:selenium Web驱动程序isDisplayed()不工作
- 为什么Javascript不从Adobe Bridge返回值
- 如何在webview(javaFX)中使用javascript(bridge)调用的executeScript
- QtWebkit javascript bridge,无法访问 Qt 对象方法
- iOS JavaScript bridge
- 使用GTK+ Webkit Webview(和Qt Webkit bridge)从JavaScript / HTML调用