使用WKWebView 学习记录:
WKWebView 和 Safari浏览器一样 用的是 Nirtro JavaScript 引擎
可以做一些UIWebView你不能做的事情(我遇到的,我用UIWebView 加载H5 其中H5中 调用手机的相册和录制视频功能,使用没有反应,点击没有效果,后来换成WKWebView 就可以使用,我想和它使用JavaScript引擎有关系吧)
更多相关内容: http://nshipster.cn/wkwebkit/
#define ScreenWidth [UIScreen mainScreen].bounds.size.width
#define ScreenHeight [UIScreen mainScreen].bounds.size.height
_webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight)];
[self.view addSubview:_webView];
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
_webView.UIDelegate = self;
_webView.navigationDelegate = self;
UIBarButtonItem * leftBackItem = [[UIBarButtonItem alloc] initWithTitle:@"Go Back" style:UIBarButtonItemStylePlain target:self action:@selector(leftButtonClick)];
self.navigationItem.leftBarButtonItem = leftBackItem;
-(void)leftButtonClick{
if ([self.webView canGoBack]) {
[self.webView goBack];
}else{
NSLog(@"***** 当前处理栈顶 ****");
}
}
//类似UIWebView的 -webViewDidStartLoad:页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
NSLog(@"***** 页面开始加载 *****");
}
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
NSLog(@"***** 服务器开始返回内容 *****");
}
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
//页面加载完成 后将navigationBar的标题修改成 网页的标题
if(webView.title && webView.title.length > 0) {
self.title= webView.title;
}
}
// 类似 UIWebView 的- webView:didFailLoadWithError:页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{
NSLog(@"***** 加载网页失败,网络故障! *****");
}
// 接收到服务器跳转请求之后再执行
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
NSLog(@"***** 接收到服务器跳转请求之后再执行 *****");
}
// 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
NSLog(@"***** 收到服务器响应,是否跳转 *****");
/*
WKNavigationResponsePolicyCancel,//不同意跳转
WKNavigationResponsePolicyAllow,//同意跳转
*/
decisionHandler(WKNavigationResponsePolicyAllow);
}
// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSString *urlString = [[navigationAction.request URL] absoluteString];
urlString = [urlString stringByRemovingPercentEncoding];
NSLog(@"Requset URL = %@",urlString);
// 用'://'截取字符串
NSArray *urlComps = [urlString componentsSeparatedByString:@"://"];
if ([urlComps count]) {
// 获取协议头
NSString *protocolHead = [urlComps objectAtIndex:0];
NSLog(@"Protocol Header = %@",protocolHead);
}
/*
WKNavigationResponsePolicyCancel,//不同意跳转
WKNavigationResponsePolicyAllow,//同意跳转
*/
decisionHandler(WKNavigationActionPolicyAllow);
}
//1.创建一个新的WebVeiw
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
WKFrameInfo *frameInfo = navigationAction.targetFrame;
if (![frameInfo isMainFrame]) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
//2.WebVeiw关闭(9.0中的新方法)
- (void)webViewDidClose:(WKWebView *)webView{
NSLog(@"%s",__func__);
}
//3.显示一个JS的Alert(与JS交互)
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
// js 里面的alert实现,如果不实现,网页的alert函数无效
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){
completionHandler();
}]];
[self presentViewController:alertController animated:YES completion:nil];
}
//4.弹出一个输入框(与JS交互的)
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
completionHandler(@"Client Not handler");
}
//5.显示一个确认框(JS的)
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
UIAlertController *alertCtl = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertCtl addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction*action){
completionHandler(YES);
}]];
[alertCtl addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction*action){
completionHandler(NO);
}]];
[self presentViewController:alertCtl animated:YES completion:nil];
}
上面的全是WKWebView的代理方法
值得一提的是
//1.创建一个新的WebVeiw
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
WKFrameInfo *frameInfo = navigationAction.targetFrame;
if (![frameInfo isMainFrame]) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
这个方法在点击H5页面中的链接 跳转的时候会调用 最开始的时候 我直接写
return self.webView
运行 点击的时候程序直接crash
报错:
** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Returned WKWebView was not created with the given configuration.**
原因呢:
每次点击H5中的line会跳转一个新网页,"_black" 是开一个新的页面 打开网页,和Safari中点加号一样!
当然在应用中如果不实现和Safari一样的效果 那就只能让其在当前页面中 重新加载一次新link
还有一种解决方法:
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
//如果是跳转一个新页面
if (navigationAction.targetFrame == nil) {
[webView loadRequest:navigationAction.request];
}
decisionHandler(WKNavigationActionPolicyAllow);
}
进度条问题:
[_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"estimatedProgress"]) {
NSLog(@"new = %@ ;",change[@"new"]);
self.progressView.progress = [change[@"new"] floatValue];
}
if (self.progressView.progress == 0) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.progressView.hidden = YES;
});
}
}
不要忘了 移除KVO的监听了!
WKWebView 与js 交互参考 http://www.jianshu.com/p/c59dd41c3631