WKWebView 小记
2018-08-15 本文已影响27人
秀才不才
WKWebView 不支持点击处理电话,邮件等格式化的URL,暂时记录下简单的webView处理
URL 特殊字符编码:
iOS9.0 之前:
NSString *encodedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,(CFStringRef)urlStr,(CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]",NULL,kCFStringEncodingUTF8));
iOS9.0 之后:
NSString *encodedUrl = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]
WebView初始化 Session同步
//初始化时注入sessionID 暂时用着没问题
NSString *cookieStr = [NSString stringWithFormat:@"document.cookie='%@=%@;path=/';",ShareManager.urlCookie.name,ShareManager.urlCookie.value];
WKUserScript *wkScript = [[WKUserScript alloc] initWithSource:cookieStr injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
WKUserContentController *contentC = [[WKUserContentController alloc] init];
[contentC addUserScript:wkScript];
WKWebViewConfiguration *wkConfig = [[WKWebViewConfiguration alloc] init];
wkConfig.userContentController = contentC;
webView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:wkConfig];
//URL监听 记着释放
[self.wkWebView addObserver:self forKeyPath:@"URL" options:NSKeyValueObservingOptionNew context:nil];
WebView frame不正确的时候写了下面方法
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (@available(iOS 11.0, *)) {
CGRect safeFrame = self.view.safeAreaLayoutGuide.layoutFrame;
[self.wkWebView setFrame:CGRectMake(0, self.backOriginView.frame.origin.y, self.view.frame.size.width, safeFrame.size.height)];
}
else
{
float height = [[UIApplication sharedApplication] statusBarFrame].size.height;
if (!self.navigationController.navigationBarHidden) {
height = 0;
}
[self.wkWebView setFrame:CGRectMake(0, height, ScreenWidth, self.view.frame.size.height - height)];
}
}
WebBridge 注入JS交互
第三方 `WebViewJavascriptBridge`类
registerHandler
callHandler
//JS方法退出Web类需要手动移除,否则类不释放
[self.bridge removeHandler:js];
可以判断页面退出吗???主要是手势返回
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
if (!self.navigationController && //navigation
!self.tabBarController && //tabbar
!self.presentingViewController) //present
{
[self deleteHanderMethod];
}
}
不这样会导致内存泄露???
在viewWillAppear设置
if (self.bridge) {
//不设置 WKWebView 代理不执行
[self.bridge setWebViewDelegate:self];
}
在viewWillDisappear 设置
[self.bridge setWebViewDelegate:nil];
WebViewDelegate
//绕过证书认证
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,card);
}else {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
}
//页面开始加载
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
//
}
//页面加载完成
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
//
}
//页面加载失败
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
//
}
//收到响应后是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
decisionHandler(WKNavigationResponsePolicyAllow);
}
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSURL *linkUrl = navigationAction.request.URL;
if (navigationAction.navigationType == WKNavigationTypeLinkActivated && [self.urlStr containsString:@"jumpWebUrl=1"]) {
//url包含jumpWebUrl=1字段 允许跳转外部链接
if (![linkUrl.host containsString:webView.URL.host]) {
//当前链接域名不一致 跳转新H5类
[self goWebViewController:@"" urlStr:navigationAction.request.URL.absoluteString];
decisionHandler(WKNavigationActionPolicyCancel);
return;//不return崩溃
}
}
NSString *urlScheme = linkUrl.scheme;
if (urlScheme.length && ([linkUrl.host containsString:@"itunes.apple.com"] || ![urlScheme containsString:@"http"])) {
NSString *scheme = @"";
if ([urlScheme isEqualToString:@"tel"]) {
scheme = @"telprompt";//拨打电话☎️会弹窗提示
} else {
scheme = urlScheme;
}
if (IOS10_OR_LATER) {
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@:%@",scheme,[linkUrl resourceSpecifier]]] options:@{} completionHandler:nil];
} else {
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@:%@",scheme,[linkUrl resourceSpecifier]]]];
}
decisionHandler(WKNavigationActionPolicyCancel);
return;//不return崩溃
}
if (navigationAction.targetFrame == nil) {
[webView loadRequest:navigationAction.request];
}
decisionHandler(WKNavigationActionPolicyAllow);
}
//弹窗
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
//
}
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
//
}
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {
//
}
其他方法
goBack; //处理显示`返回``关闭`按钮
//禁止缩放 方法不是很完美
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return nil;
}
其他缩放方法(没测试):这里