由于项目使用到了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)];
//设置代理用来获取加载状态等等信息...<WKUIDelegate,WKNavigationDelegate>
_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代码。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>walletProj</title>
</head>
<body>
<script type="text/javascript">
//无参数函数
function testA() {
alert("a");
}
//有参数函数
function testB(value) {
alert(value);
}
function testC(value) {
//返回值可以是很多类型。
//反馈字符串
return value + "value";
//返回对象,如果需要传递给oc的东西有很多,就可以构造一个这样的对象用来传输。
// var finalObj = {"name":"chaman","age":"18","sex":"male"};
// return finalObj;
}
</script>
</body>
</html>
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];
//需要实现<WKScriptMessageHandler>,可同时注册多个方法名字,但是记得在控制器销毁时候移除。
[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];
//设置代理用来获取加载状态等等信息...<WKUIDelegate,WKNavigationDelegate>
_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(<数据>))
<head>
<meta charset="UTF-8">
<title>walletProj</title>
</head>
<body>
<script type="text/javascript">
//无参数函数
function testA() {
window.webkit.messageHandlers.jsCallOc.postMessage("");
}
//有参数函数
function testB(value) {
window.webkit.messageHandlers.jsCallOc.postMessage("call oc");
}
function testC(value) {
var finalObj = { "name": "chaman", "age": "18", "sex": "male" };
window.webkit.messageHandlers.jsCallOc.postMessage(finalObj);
}
</script>
</body>
</html>
在控制器销毁的时候移除方法名
- (void)dealloc {
[[_webView configuration].userContentController removeScriptMessageHandlerForName:@"jsCallOc"];
}