在Hybrid架构中,原生界面和web页面需要频繁地沟通,并且是双向的沟通。原生代码可以构建JavaScript语句,交由webview进行执行,从而在web页面上实现需要的效果。而在web页面的js文件中,也可以调用原生的Objective-C方法,从而执行一些原生方法才能完成的操作。与此相关的库有WebViewJavascriptBridge以及JavaScriptCore,有需要的同学可以自行了解。
WKWebView iOS(8.0)
用以替代 UIKit 中笨重难用、内存泄漏的 UIWebView。WKWebView 拥有60fps滚动刷新率、和 safari 相同的 JavaScript 引擎等优势。
iOS下JS与OC互相调用(一)--UIWebView 拦截URL
iOS下JS与OC互相调用(二)--WKWebView 拦截URL
iOS下JS与OC互相调用(三)--MessageHandler
iOS下JS与OC互相调用(四)--JavaScriptCore
iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge
iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge
iOS下JS与OC互相调用(八)--Cordova详解+实战
JS调用OC
方式一 拦截请求 :
UIWebView
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
WKWebView
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
如果在WKWebView中使用alert、confirm 等弹窗,就得实现WKWebView的WKUIDelegate中相应的代理方法。
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
方法二
MessageHandler
WKUserContentController对象有一个方法- addScriptMessageHandler:name:,我把这个功能简称为MessageHandler。
1)初始化 configuration
2)对象可以添加多个scriptMessageHandler
[self.webView.configuration.userContentController addScriptMessageHandler:selfname:@"ScanAction"];
3)实现WKScriptMessageHandler协议
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message{
// message.body -- Allowed types are NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull.
if([message.name isEqualToString:@"ScanAction"]) {
NSLog(@"扫一扫");
4 在willdisappear中移除
// 因此这里要记得移除handlers[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"ScanAction"];
OC调用JS
方式一
UIWebView
NSString *jsStr = [NSString stringWithFormat:@"showAlert('%@')",@"这里是JS中alert弹出的message"];
[_webView stringByEvaluatingJavaScriptFromString:jsStr];
WKWebView
WKWebView 提供了一个新的方法evaluateJavaScript:completionHandler:,实现OC 调用JS 等场景。
WebViewJavascriptBridge
UIWebView WKWebView通用
1,
_webViewBridge = [WKWebViewJavascriptBridge bridgeForWebView:self.webView];
2
// 如果控制器里需要监听WKWebView 的`navigationDelegate`方法,就需要添加下面这行。[_webViewBridge setWebViewDelegate:self];
3 register a handler in objec and call a JS handler
[_webViewBridge registerHandler:@"locationClick" handler:^(iddata, WVJBResponseCallback responseCallback) {
// 获取位置信息
NSString *location =@"广东省深圳市南山区学府路XXXX号";// 将结果返回给js
responseCallback(location);
}
];
[_webViewBridge callHandler:@"testJSFunction" data:@"一个字符串"responseCallback:^(idresponseData) {
NSLog(@"调用完JS后的回调:%@",responseData);
}];
JavaScriptCore
在iOS 7之后,apple添加了一个新的库JavaScriptCore,用来做JS交互,因此JS与原生OC交互也变得简单了许多。
首先导入JavaScriptCore库, 然后在OC中获取JS的上下文
- (void)webViewDidFinishLoad:(UIWebView*)webView{
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//定义好JS要调用的方法, share就是调用的share方法名
context[@"share"] = ^() {
NSLog(@"+++++++Begin Log+++++++");
NSArray*args = [JSContext currentArguments];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView*alertView = [[UIAlertViewalloc] initWithTitle:@"方式二"message:@"这是OC原生的弹出窗"delegate:selfcancelButtonTitle:@"收到"otherButtonTitles:nil]; [alertView show];
});
for(JSValue *jsValinargs) {
NSLog(@"%@", jsVal.toString);
}
NSLog(@"-------End Log-------"); };
}
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
NSString*textJS =@"showAlert('这里是JS中alert弹出的message')";
[context evaluateScript:textJS];
另一种方法
// 相当于evaluateScript:
[[JSContext currentContext][@"payResult"] callWithArguments:@[@"支付成功"]];
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
[context evaluateScript:@"var arr = [3, 4, 'abc'];"];
如果我们在OC中想要取出arr,只需要这样:
JSValue *value = context[@"arr"];
网友评论