iOS|iOS WKWebView
WKWebView
是iOS8之后推出来的控件,目的是为了取代UIWebView
。
WKWebView
相比UIWebView
有这些优点:
- 1、支持更多的html5特性
- 2、支持高达60fps的滚动刷新率以及内置手势
- 3、与safari相同的javascript引擎
- 4、不会占用更多的内存
一、创建
创建配置
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKUserContentController* userContent = [[WKUserContentController alloc] init];
// 添加消息处理,注意:self指代的对象需要遵守WKScriptMessageHandler协议,结束时需要移除
//这个类似uiwebview于js交互里的JSContext创建js对象。例如context["log"] = self;
//但是js通过log发起调用时是不一样的[userContent addUserScript:wkUScript];
[userContent addScriptMessageHandler:self name:@"log"];
//这里的scriptMessageHandler代理一定要实现// 将UserConttentController设置到配置文件
config.userContentController = userContent;
WKWebView *_wkWebview = [[WKWebView alloc]initWithFrame:self.view.frame configuration:config];
_wkWebview.UIDelegate = self;
_wkWebview.navigationDelegate = self;
_wkWebview.allowsBackForwardNavigationGestures = YES;
//支持手势返回
二、各种代理
//通过js调用原生方法触发的方法
//例如:js里执行这段函数window.webkit.messageHandlers.log.postMessage({'abc':'def'})就可以调起WKScriptMessageHandler的协议方法
#pragma mark-- WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {NSLog(@"message name is %@",message.name);
//表示web在js里注册的对象名字
NSLog(@"message body is %@",message.body);
//h5传递的数据
NSLog(@"message frameInfo is %@",message.frameInfo);
}#pragma mark-- WKUIDelegate- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
NSLog(@"点击了取消按钮==%@",message);
}])];
[alertController addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
NSLog(@"点击了确定按钮==%@",message);
}])];
[self presentViewController:alertController animated:YES completion:^{
NSLog(@"alert show");
}];
}- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler {NSLog(@"%s",__FUNCTION__);
completionHandler(YES);
}- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler {NSLog(@"%s",__FUNCTION__);
completionHandler(defaultText);
//input控件里的内容回调}- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
NSLog(@"%s",__FUNCTION__);
WKFrameInfo *frameInfo = navigationAction.targetFrame;
if (![frameInfo isMainFrame]) {
[webView loadRequest:navigationAction.request];
}
return nil;
}#pragma mark-- WKNavigationDelegate- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {NSLog(@"%s",__FUNCTION__);
}- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {NSLog(@"%s",__FUNCTION__);
}- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {NSLog(@"%s",__FUNCTION__);
[self.wkWebview evaluateJavaScript:@"document.title" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
NSLog(@"item is %@ error is %@",item,error);
//item的值是执行javaScript的返回值.如果error有值就表示执行javaScript出错了
}];
NSHTTPCookie *cookie;
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [cookieJar cookies]) {
NSLog(@"cookie is %@", cookie);
}}- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {NSLog(@"%s",__FUNCTION__);
NSLog(@"error is %@",error);
}- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {NSLog(@"%s",__FUNCTION__);
[webView.configuration.userContentController removeScriptMessageHandlerForName:@"log"];
NSLog(@"error is %@",error);
}- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {NSLog(@"%s",__FUNCTION__);
//在发送请求之前,决定是否跳转
//处理打电话的功能
NSURL *URL = navigationAction.request.URL;
NSLog(@"获取到URL========%@",URL);
NSString *scheme = [URL scheme];
UIApplication *app = [UIApplication sharedApplication];
// 打电话
if ([scheme isEqualToString:@"tel"]) {
if ([app canOpenURL:URL]) {
[app openURL:URL];
// 一定要加上这句,否则会打开新页面
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
}NSLog(@"headers is %@ %d",navigationAction.request.allHTTPHeaderFields,navigationAction.request.HTTPShouldHandleCookies);
decisionHandler(WKNavigationActionPolicyAllow);
}- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
NSLog(@"%s",__FUNCTION__);
//接收到服务器响应之后决定是否跳转
decisionHandler(WKNavigationResponsePolicyAllow);
}
//https权限认证
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
if ([challenge previousFailureCount] == 0) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
NSLog(@"%s",__FUNCTION__);
}
三、wkwebview调用
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[_wkWebview loadRequest:urlRequest];
四、JS调用Native
//必须使用设置的代理进行调动,比如我们设置了log
window.webkit.messageHandlers.log.postMessage('h5给native发送一条消息');
五、Native调用JS
两种方式:
//第一种,web执行js代码,下面是获取网页tittle的示例
[self.wkWebview evaluateJavaScript:@"document.title" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
NSLog(@"item is %@ error is %@",item,error);
//item的值是执行javaScript的返回值.如果error有值就表示执行javaScript出错了
}];
//第二种,通过WKUserScript执行js代码
[self.wkWebview.configuration.userContentController addUserScript:[[WKUserScript alloc]initWithSource:@"alert('wk弹框')" injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES] ];
/* WKUserScriptInjectionTimeAtDocumentEnd表示document结构渲染完成之后,子目录完成之前
forMainFrameOnly表示YES只在主窗口渲染,NO是在全局窗口渲染
*/
【iOS|iOS WKWebView】更新时间: 2018-09-18
推荐阅读
- 2020-04-07vue中Axios的封装和API接口的管理
- iOS中的Block
- 记录iOS生成分享图片的一些问题,根据UIView生成固定尺寸的分享图片
- 2019-08-29|2019-08-29 iOS13适配那点事
- Hacking|Hacking with iOS: SwiftUI Edition - SnowSeeker 项目(一)
- iOS面试题--基础
- 接口|axios接口报错-参数类型错误解决
- iOS|iOS 笔记之_时间戳 + DES 加密
- OC:|OC: WKWebView详解
- iOS,打Framework静态库