由于项目使用到了oc与js混编,oc与js交互可以用UIWebView也可以用WKWebView,这里我说一下通过WKWebView加载HTML(本地/网络)文件来进行交互,官方推荐在嵌入h5页面或者需要交互的时候都使用WKWebView而不是使用UIWebView。WKWebView需要最低系统为8.0。
一:加载HTML
加载wkWebView的时候可以设置很多配置参数。需要用到的地方会写。
_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
//设置代理用来获取加载状态等等信息...
_webView.UIDelegate = self;
_webView.navigationDelegate = self;
[self.view addSubview:_webView];
//加载本地html
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"testFunction" ofType:@"html"];
[_webView loadFileURL:[NSURL fileURLWithPath:filePath] allowingReadAccessToURL:[NSBundle mainBundle].resourceURL];
二:OC调用JS
oc如果需要调用js方法。需要在html加载完成的代理方法中实现。
//html加载失败
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
NSLog(@"error message:%@",error);
}
//html开始加载
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
NSLog(@"begin load html");
}
//html加载完成
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
NSLog(@"finish load");
WEAKSELF;
[webView evaluateJavaScript:@"" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
NSLog(@"response: %@ error: %@", response, error);
}];
}
这里大概3种情况。
1.oc调用js无参数函数。
2.oc调用js有参数函数。
3.oc调用js函数后,有返回值。
html代码。
walletProj
OC代码。
注意:在wkwebView中如果html有弹框处理(alert函数),oc这边是不能显示的,必须实现代理方法- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler。
从中获取alert内容并做处理。
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
NSLog(@"finish load");
//调用js无参函数
[webView evaluateJavaScript:@"testA()" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
//js函数调用return,这里才会有东西,否则无任何信息。
NSLog(@"response: %@ error: %@", response, error);
}];
//调用js有参函数
[webView evaluateJavaScript:[NSString stringWithFormat:@"testB('%@')",@"show"] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
//js函数调用return,这里才会有东西,否则无任何信息。
NSLog(@"response: %@ error: %@", response, error);
}];
//调用js有参函数并获得返回值
[webView evaluateJavaScript:[NSString stringWithFormat:@"testC('%@')",@"return value"] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
//js函数调用return,这里才会有东西,否则无任何信息。
NSLog(@"response: %@ error: %@", response, error);
}];
}
二:JS调用OC
比如我OC有一个方法叫"jsCallOc",JS在某些场景需要调用OC的这个函数。
1.oc需要注册"jsCallOc"这个方法,在初始化WKWebView的时候注入进去,这时候初始化WKWebView就应该这样写,需要实现WKScriptMessageHandler代理。
//注册方法
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
//需要实现,可同时注册多个方法名字,但是记得在控制器销毁时候移除。
[userContentController addScriptMessageHandler:self name:@"jsCallOc"];
// WKWebView的配置
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContentController;
_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 10, 10) configuration:configuration];
//设置代理用来获取加载状态等等信息...
_webView.UIDelegate = self;
_webView.navigationDelegate = self;
[self.view addSubview:_webView];
//加载本地html
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"testFunction" ofType:@"html"];
[_webView loadFileURL:[NSURL fileURLWithPath:filePath] allowingReadAccessToURL:[NSBundle mainBundle].resourceURL];
2.实现代理方法获取js调用的操作。
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
//获取值
NSLog(@"data:%@", message.body);
//获取函数名字
NSLog(@"data:%@", message.name);
}
JS代码(JS调用OC需要按照特定格式:window.webkit.messageHandlers.<方法名>.postMessage(<数据>))
walletProj