混合开发中, 重点在于Native与H5的混合使用,那么JavaScript 和 Objective-C 交互也就成为了重中之重。
JS与OC的交互iOS方向大致分为三种:传统WebView的代理方法、JavaScriptCore、第三方框架。
本文围绕目前优秀的第三方框架 WebViewJavascriptBridge 展开.
1. 准备文件, 导入 WebViewJavascriptBridge
$ pod 'WebViewJavascriptBridge'
2. 引入头文件、创建webView, 加载.html文件
#import <WebViewJavascriptBridge/WebViewJavascriptBridge.h>
- (void)creatSubViews {
self.view.backgroundColor = [UIColor whiteColor];
_webView = [[UIWebView alloc]init];
_webView.frame = self.view.bounds;
_webView.delegate = self;
_webView.backgroundColor = [UIColor whiteColor];
_webView.scrollView.showsHorizontalScrollIndicator = NO;
_webView.scrollView.bounces = NO;
[self.view addSubview:_webView];
}
3. 初始化WebViewJavascriptBridge实例、声明JS交互
@interface HybridViewController ()
@property (nonatomic, strong) WebViewJavascriptBridge *bridge;
@end
WebViewJavascriptBridge实例
- (void)creatBridge {
///1. 开启日志, 方便调试
[WebViewJavascriptBridge enableLogging];
///2. 给ObjC与JS建立桥梁
self.bridge = [WebViewJavascriptBridge bridgeForWebView:_webView];
///3. 设置代理
[self.bridge setWebViewDelegate:self];
}
声明JS交互, 直接copy到<script>
中即可
function setupWebViewJavascriptBridge(callback)
{
if (window.WebViewJavascriptBridge) {
return callback(WebViewJavascriptBridge);
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback);
}
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() {
document.documentElement.removeChild(WVJBIframe);
}, 0)
}
处理JS交互
setupWebViewJavascriptBridge(function(bridge) {
///JavaScript 给 Objective-C 发送 消息
dom.onmousedown = function () {
bridge.callHandler('loginAction',{"userID":"123", "name":"JS"}, function(response)
{
//处理OC过来的回调
alert('收到oc过来的回调:'+response)
}));
};
/// 监听Objective-C消息
bridge.registerHandler('registerAction', function(data, responseCallback)
{
alert('OC给JS, 传递的数据为:'+data)
/// 告诉OC,JS消息接收成功
var responseData = { 'result':'handle success' }
responseCallback(responseData)
}
});
4. 添加JS事件监听, 发送消息给JS
- 添加JavaScript事件监听, JavaScript => OC
- (void)addObserverForJavaScript{
/**
类似添加JS事件监听
@param registerHandler 要注册的事件名称(比如这里我们为loginAction)
@param handel Block回调函数, 当JS中bridge对象触发了`loginAction`此方法时, 发生回调
@param data JS端传递过来的数据
@param responseCallback OC通知JS的回调函数
registerHandler 是Objc和JavaScript
*/
[self.bridge registerHandler:@"loginAction" handler:^(id data, WVJBResponseCallback responseCallback)
{
NSLog(@"接收到JavaScript传递Objc的消息");
responseCallback(@"JavaScript, Objc已承购接收到消息");
}];
}
- Objective-C 发送 消息 给 JavaScript
- (void)sendMessageToJavaScript{
///5. 直接调用JS端注册的HandleName
[self.bridge callHandler:@"registerAction" data:@{@"foo": @"before ready"} responseCallback:^(id responseData) {
NSLog(@"oc请求js后接受的回调结果:%@",responseData);
}];
}
5. 最终实现
- (void)viewDidLoad {
[super viewDidLoad];
/*添加子视图*/
[self creatSubViews];
/*创建桥接*/
[self creatBridge];
/*加载HTML文件*/
[self loadRequestForHTML];
//申明js调用oc方法的处理事件,这里写了后,h5那边只要请求了,oc内部就会响应
[self addObserverToJavaScript];
///两秒后给JS发送消息
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self sendMessageTOJavaScript];
});
}
其实关键在于: OC和JS商定的方法名要统一
bridge.registerHandler方法名 对应 bridge.callHandler方法名
JS CallHandler => OC Register
OC CallHandler => JS Register