自己封装的WKWebView,功能如下:
1、加载网页URL
2、网页转跳返回
3、与网页之间的交互事件
4、退出界面清除缓存
5、释放内存,防止内存溢出
使用方法:
HBWebViewVC *vc = [[HBWebViewVC alloc]init];
vc.url = @"https://www.baidu.com";
[self.navigationController pushViewController:vc animated:YES];
部分关键代码:
#pragma mark 初始化webview
-(void)initWKWebView{
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
configuration.preferences.javaScriptEnabled = YES;//打开js交互
//这两个方法有内存泄漏,需要解决一下
[configuration.userContentController addScriptMessageHandler:self name:@"Native"];
[configuration.userContentController addScriptMessageHandler:self name:@"callApp"];
configuration.preferences.minimumFontSize = 0;
_webConfiguration = configuration;
_jsHandler = [[HBJSHandler alloc]initWithViewController:self configuration:configuration];
_webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-bAllNavTotalHeight-kBottomSafeHeight) configuration:configuration];
_webView.scrollView.backgroundColor = [UIColor whiteColor];
[self.webView setOpaque:NO];
_webView.navigationDelegate = self;
_webView.backgroundColor = [UIColor whiteColor];
_webView.allowsBackForwardNavigationGestures =YES;//打开网页间的 滑动返回
_webView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
//监控进度
[_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
[_webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
[self.view addSubview:_webView];
//进度条
_progressView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleDefault];
_progressView.tintColor = [UIColor redColor];
_progressView.trackTintColor = [UIColor clearColor];
_progressView.frame = CGRectMake(0, 0, self.view.bounds.size.width, 5.0);
[_webView addSubview:_progressView];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:_url]];
[_webView loadRequest:request];
NSLog(@"打印一下网页链接:%@",_url);
//更新导航栏按钮
[self updateNavigationItems];
}
#pragma mark ==========KVO 监测进度==========
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"estimatedProgress"] && object == self.webView) {
self.progressView.progress = self.webView.estimatedProgress;
if (self.progressView.progress == 1) {
__weak typeof (self)weakSelf = self;
[UIView animateWithDuration:0.25f delay:0.3f options:UIViewAnimationOptionCurveEaseInOut animations:^{
weakSelf.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.4f);
} completion:^(BOOL finished) {
weakSelf.progressView.hidden = YES;
}];
}
}else if ([keyPath isEqualToString:@"title"] && object == self.webView){//网页title
NSInteger titleLength = 0;
if (kUI_IPHONE5) {
titleLength = 6;
}else if (kUI_IPHONE6){
titleLength = 9;
}else if (kUI_IPHONE6PLUS){
titleLength = 12;
}else{
titleLength = 9;
}
if (self.webView.title.length > titleLength) {
NSString *titleStr = [self.webView.title substringToIndex:titleLength];
self.title = [NSString stringWithFormat:@"%@...",titleStr];
}else{
self.title =self.webView.title;
}
}else{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"方法名:%@", message.name);
NSLog(@"参数:%@", message.body);
//自定义参数,这个可以跟前端后台统一参数,可以传字典类型
//[HBClickEventManage GTPushViewController:nil andPushVC:self isPushType:2 ClickType:[message.body objectForKey:@"function"] clickParameter:[message.body objectForKey:@"parameters"] ClickUrl:@"" Title:@""];
}
#pragma mark ==========加载完成==========
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSString *injectionJSString = @"var script = document.createElement('meta');"
"script.name = 'viewport';"
"script.content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0, user-scalable=no\";"
"document.getElementsByTagName('head')[0].appendChild(script);";
[webView evaluateJavaScript:injectionJSString completionHandler:nil];
//更新进度调
[self updateProgress:webView.estimatedProgress];
//更新导航栏按钮
[self updateNavigationItems];
}
#pragma mark ==========更新进度条==========
-(void)updateProgress:(double)progress{
self.progressView.alpha = 1;
if(progress > _lastProgress){
[self.progressView setProgress:self.webView.estimatedProgress animated:YES];
}else{
[self.progressView setProgress:self.webView.estimatedProgress];
}
_lastProgress = progress;
if (progress >= 1) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.progressView.alpha = 0;
[self.progressView setProgress:0];
self.lastProgress = 0;
});
}
}
//加载失败 隐藏progressView
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
self.progressView.hidden = YES;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
#pragma mark ==========判断链接是否允许跳转==========
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSURL *URL = navigationAction.request.URL;
NSString *scheme = [URL scheme];
// 打电话
if ([scheme isEqualToString:@"tel"]) {
UIApplication *app = [UIApplication sharedApplication];
if ([app canOpenURL:URL]) {
[app openURL:URL];
// 一定要加上这句,否则会打开新页面
decisionHandler(WKNavigationActionPolicyCancel); return;
}
} // 打开淘宝
if ([scheme isEqualToString:@"tbopen"]) {
if (!self.isTBDidLoad) {//避免重复跳淘宝开关
UIApplication *app = [UIApplication sharedApplication];
if ([app canOpenURL:URL]) {
[app openURL:URL];
// 一定要加上这句,否则会打开新页面
self.isTBDidLoad = YES;
decisionHandler(WKNavigationActionPolicyCancel); return;
}
}else{
decisionHandler(WKNavigationActionPolicyAllow); return;
}
} // 打开appstore
if ([URL.absoluteString containsString:@"ituns.apple.com"]) {
UIApplication *app = [UIApplication sharedApplication];
if ([app canOpenURL:URL]) {
[app openURL:URL];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}
//如果是跳转一个新页面
if (navigationAction.targetFrame == nil) {
[webView loadRequest:navigationAction.request];
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
// * 拿到响应后决定是否允许跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
decisionHandler(WKNavigationResponsePolicyAllow);
}
#pragma mark ==========继承方法==========
-(void)closeItemInNaviClicked{
NSLog(@"closeItemInNaviClicked");
}
#pragma mark - update nav items
-(void)updateNavigationItems{
NSLog(@"canGoBack ==%d",self.webView.canGoBack);
if (self.webView.canGoBack) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
[self addWebNavigationItemWithTitles:@[@"mine_back_share_img", @"close_treasure_img"] isLeft:YES target:self action:@selector(leftBtnClick:) tags:@[@2000,@2001]];
}else{
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
[self addWebNavigationItemWithTitles:@[@"mine_back_share_img"] isLeft:YES target:self action:@selector(leftBtnClick:) tags:@[@2000]];
}
}
- (void)addWebNavigationItemWithTitles:(NSArray *)titles isLeft:(BOOL)isLeft target:(id)target action:(SEL)action tags:(NSArray *)tags{
NSMutableArray * items = [[NSMutableArray alloc] init];
NSInteger i = 0;
for (NSString *imgNameStr in titles) {
UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0, 0, 44 , 44);
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[btn setImage:[UIImage imageNamed:imgNameStr] forState:UIControlStateNormal];
if (i==0) {
btn.backgroundColor = [UIColor redColor];
}else{
btn.backgroundColor = [UIColor blueColor];
}
[btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
btn.tag = [tags[i++] integerValue];
UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithCustomView:btn];
[items addObject:item];
}
if (isLeft) {
self.navigationItem.leftBarButtonItems = items;
} else {
self.navigationItem.rightBarButtonItems = items;
}
}
-(void)customBackItemClicked{
self.webView.canGoBack? [self.webView goBack]: [self backBtnInNaviClicked];
}
#pragma mark ==========点击关闭按钮==========
-(void)closeWeb{
NSLog(@"调用关闭按钮");
[_jsHandler cancelHandler];
[self.navigationController popViewControllerAnimated:YES];
}
最后附上DEMO地址
如果能帮助到你请点赞评论支持,谢谢!
END.