在iOS8以后苹果开始提供新的组件WKWebView,其框架为webkit,框架的推出,有效的用WKWebView替代了UIWebView,WKWebView无论在加载耗时或者内存占用上都要优于UIWebView,在功能上有更完善的交互体系,可以让OC与JS的沟通更加明显易读,根据实际的项目测试,使用WKWebView的内存占用率仅仅是UIWebView的1/3~1/4,这么大的内存占用差距,还是让很多开发者或者公司感兴趣的,其次是对H5的支持和JS的更广泛使用,代理方面也细分的更加明确;
接下来直入正题吧;
使用WKWebView需要导入头文件#import <WebKit/WebKit.h>
WKWebView中调用JS使用的方法是:
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
初始化WKWebView
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// 设置偏好设置
config.preferences = [[WKPreferences alloc] init];
// 默认为0
config.preferences.minimumFontSize = 0;
// 默认认为YES
config.preferences.javaScriptEnabled = YES;
// iOS上默认为NO,表示不能自动通过窗口打开
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
//UserContentController提供javaScript向webView发送消息的方法
WKUserContentController *userContent = [[WKUserContentController alloc] init];
//添加消息处理
[userContent addScriptMessageHandler:self name:@"firstMethod"];
[userContent addScriptMessageHandler:self name:@"secondMethod"];
//将UserContentController设置到配置文件中
config.userContentController = userContent;
_wkWebview = [[WKWebView alloc]initWithFrame:CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-64) configuration:config];
_wkWebview.UIDelegate = self;
_wkWebview.navigationDelegate = self;
[self.view addSubview:_wkWebview];
[_wkWebview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.1.101/php/demo1.html"]]];
OC调JS,创建两个按钮,分别无参数调用JS和有参数调用JS:
UIButton *button1 = [[UIButton alloc]initWithFrame:CGRectMake(20, [UIScreen mainScreen].bounds.size.height - 64, 105, 50)];
button1.layer.cornerRadius = 25;
button1.layer.masksToBounds = YES;
[button1 setTitle:@"调JS无参数" forState:UIControlStateNormal];
button1.backgroundColor = [UIColor grayColor];
[self.view addSubview:button1];
[button1 addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
UIButton *button2 = [[UIButton alloc]initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width - 125, [UIScreen mainScreen].bounds.size.height - 64, 105, 50)];
button2.layer.cornerRadius = 25;
button2.layer.masksToBounds = YES;
[button2 setTitle:@"调JS有参数" forState:UIControlStateNormal];
button2.backgroundColor = [UIColor grayColor];
[self.view addSubview:button2];
[button2 addTarget:self action:@selector(buttonClickWithName) forControlEvents:UIControlEventTouchUpInside];
- (void)buttonClick
{
[self.wkWebview evaluateJavaScript:@"OC_JS()" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
}];
}
- (void)buttonClickWithName
{
[self.wkWebview evaluateJavaScript:@"OC_JSWithName('hanmeimei')" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
}];
}
html代码,本人前端小白,写的不好大家勿怪:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试测试</title>
</head>
<body bgcolor="#faebd7">
<p>p标签1</p>
<p>p标签2</p>
<button style="width:100px ;height:50px" onclick="firstMethod()">调OC1</button>
<button style="width:100px ;height:50px" onclick="secondMethod()">调OC2</button>
<script>
function OC_JS() {
alert("wkwebview调用OC不带参数");
}
function OC_JSWithName(name) {
alert("wkwebview调用OC带参数:"+name);
}
function firstMethod(){
window.webkit.messageHandlers.firstMethod.postMessage("我要调用firstMethod方法");
}
function secondMethod() {
window.webkit.messageHandlers.secondMethod.postMessage("我要调用secondMethod方法");
}
</script>
</body>
</html>
注意:WKWebView如果有alert需要在OC代码实现如下方法:
#pragma mark - WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];
[alertView addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
}]];
[alertView addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *_Nonnull action){
completionHandler();
}]];
[self presentViewController:alertView animated:YES completion:nil];
}
常用代理WKNavigationDelegate
#pragma mark - WKNavigationDelegate
//开始加载时调用
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
}
//当内容开始返回时调用
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
{
}
//页面加载完成之后调用
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation
{
}
分别点击下面两个按钮调取JS方法;
JS调用OC:
为WKWebView添加消息处理:
Snip20170114_11.png
对应html代码:
Snip20170105_23.png
JS调用OC我们可以根据name和body,进行处理;
//js调用OC我们可以根据name和body,进行处理。
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
NSString *messageName = message.name;
if ([@"firstMethod" isEqualToString:messageName]) {
id messageBody = message.body;
NSLog(@"%@",messageBody);
//在这里写OC中要执行的方法
}
if([@"secondMethod" isEqualToString:messageName]){
id messageBody = message.body;
NSLog(@"%@",messageBody);
//在这里写OC中要执行的方法
}
}
Snip20170105_26.png
点击调用OC1 OC2,xcode控制台分别打印message.body
Snip20170105_27.png
网友评论