WKWebView 是 iOS8 推出的组件, 相比 UIWebView 而言, 很大程度上解决了内存占用量巨大的问题. 在这里主要说一些通过 WKWebView 来实现 Objective-C 和 JavaScript 的交互.
一、初始化 WKWebView 及其配置
//导入#import
@interface WKWebViewViewController ()
{
WKUserContentController *_userContentController;
}
@property(nonatomic,strong) WKWebView *wkWebView;
@property(nonatomic,strong) UIProgressView *progressView;
@end
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
//注册供js调用的方法
_userContentController =[[WKUserContentController alloc]init];
_userContentController =[[WKUserContentController alloc]init];
[_userContentController addScriptMessageHandler:self name:@"buttonAction"];
[_userContentController addScriptMessageHandler:self name:@"alertAction"];
[_userContentController addScriptMessageHandler:self name:@"changeNav"];
[_userContentController addScriptMessageHandler:self name:@"closeWeb"];
[_userContentController addScriptMessageHandler:self name:@"sendDic"];
configuration.userContentController = _userContentController;
configuration.preferences.javaScriptEnabled = YES;
//初始化 WKWebView
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, DEVICE_WIDTH, DEVICE_HEIGHT) configuration:configuration];
webView.backgroundColor = [UIColor clearColor];
webView.UIDelegate = self;
webView.navigationDelegate = self;
webView.allowsBackForwardNavigationGestures =YES;//打开网页间的 滑动返回
webView.allowsLinkPreview = YES;//允许预览链接
[self.view addSubview:webView];
加载 URL
//网络h5
// NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
// [webView loadRequest:[NSURLRequest requestWithURL:url]];
//加载本地H5
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
NSString * htmlPath = [[NSBundle mainBundle] pathForResource:@"JSDemo"
ofType:@"html"];
NSString * htmlCont = [NSString stringWithContentsOfFile:htmlPath
encoding:NSUTF8StringEncoding
error:nil];
[webView loadHTMLString:htmlCont baseURL:baseURL];
同时, 可以在初始化方法中, 添加对网页加载进度的监听, 设置相应的进度条:
//初始化进度条监听
[self initProgressView];
//注册 KVO 监听 拿到加载进度
[webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
#pragma mark - 初始化进度条
- (void)initProgressView {
UIProgressView *progressView =[[UIProgressView alloc]initWithFrame:CGRectMake(0,64, DEVICE_WIDTH, 10)];
progressView.tintColor = [UIColor blueColor];
progressView.trackTintColor = [UIColor whiteColor];
[self.view addSubview:progressView];
//
self.progressView = progressView;
}
#pragma mark - KVO 监听进度条
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([keyPath isEqualToString:@"estimatedProgress"]){
_progressView.hidden = NO;
CGFloat progress = [change[@"new"] floatValue];
[_progressView setProgress:progress];
if(progress == 1.0){
_progressView.hidden =YES;
}
}
}
二、实现 OC 月 JS 交互的关键方法
#pragma mark - 实现注册的供js调用的oc方法 关键
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if(message.name == nil || [message.name isEqualToString:@""]){
return;
}
//message.body : js 传过来值
NSLog(@"message.body ==%@",message.body);
//message.name js发送的方法名称
//每个方法传不传参数, 传什么类型的参数, 需要和后台确定
if([message.name isEqualToString:@"buttonAction"]){
//获取 js 传来的参数
NSString *body = [message.body objectForKey:@"body"];
[self logNumber:body];
[self uilabel:body];
NSLog(@"%@",body);
}else if ([message.name isEqualToString:@"alertAction"]){
NSString *body = [message.body objectForKey:@"body"];
[self showAlert:body];
}else if ([message.name isEqualToString:@"changeNav"]){
NSString * info =[message.body objectForKey:@"body"];
NSArray * arr =[info componentsSeparatedByString:@"&"];
[self changeNavBarColor:arr[0] title:arr[1]];
NSLog(@"js dic====%@",info);
}else if ([message.name isEqualToString:@"closeWeb"]){
[self closeWeb];
}else if ([message.name isEqualToString:@"sendDic"]){
NSDictionary *body = [message.body objectForKey:@"body"];
[self showAlert:[NSString stringWithFormat:@"%@ + %@",body[@"a"],body[@"b"]]];
}
}
#pragma mark - 实现注册的供 JS 调用的 OC方法
- (void)closeWeb {
[self.navigationController popViewControllerAnimated:YES];
}
-(void)relaodWeb {
[_wkWebView reload];
}
- (void)showAlert:(NSString * )msg {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"提示" message:msg delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
});
}
三、我们需要在页面关闭的时候, 移除注册的方法
#pragma mark - 注册的方法要在view dealloc前 remove 否则 不走 dealloc
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[_userContentController removeScriptMessageHandlerForName:@"buttonAction"];
[_userContentController removeScriptMessageHandlerForName:@"alertAction"];
[_userContentController removeScriptMessageHandlerForName:@"changeNav"];
[_userContentController removeScriptMessageHandlerForName:@"closeWeb"];
[_userContentController removeScriptMessageHandlerForName:@"sendDic"];
}
- (void)dealloc {
//移除 KVO 监听
[_wkWebView removeObserver:self forKeyPath:@"estimatedProgress"];
NSLog(@"wkWebview dealloc");
}
DEMO 下载