WKWebView是在Apple的WWDC 2014随iOS 8和OS X 10.10出来的,是为了解决UIWebView加载速度慢,占用内存大,优化困难的问题。
文章主要内容
- WKWebview新特性
- WebKit框架概览
- WKWebView属性解析
- WKNavigationDelegate协议详解
- WKUIDelegate协议详解
一,WKWebview新特性
1,在性能、稳定性、功能方面有很大提升,占用内存约为UIWebView的1/3 ~ 1/4。
2,高达60fps的滚动刷新率和丰富的内置手势。
3,更多的支持HTML5的特性。
4,具有Safari相同的JavaScript引擎。
5,允许JavaScript的Nitro库加载并使用(UIWebView中限制)。
6,将UIWebViewDelegate和UIWebView重构成了14个类与3个协议
【官方链接】(https://developer.apple.com/documentation/webkit)
二,WebKit框架概览
webkit框架如上图所示,WebKit框架中最核心的类应该属于WKWebView了,这个类专门用来渲染网页视图,其他类和协议都将基于它和服务于它。
WKWebView:网页渲染与展示,通过WKWebViewConfiguration进行自定义配置。
WKWebViewConfiguration:属性的集合,专门用来配置WKWebView。
-->WKPreference:这个类用来进行相关webView设置。
-->WKProcessPool:这个类用来配置进程池,与网页视图的资源共享有关。
-->WKUserContentController:这个类主要用来做native与JavaScript的交互管理。
---->WKUserScript:用于进行JavaScript注入。
---->WKScriptMessageHandler:用来处理JavaScript调用native的方法。
WKNavigationDelegate:网页跳转间的导航管理协议,这个协议可监听网页活动。
-->WKNavigationAction+WKNavigationResponse:
包含可能让网页导航变化的返回内容信息,用于判断是否做出导航变化。
---->WKFrameInfo: 包含一个网页的布局信息。
WKUIDelegate:用于交互处理JavaScript中的一些弹出框。
WKBackForwardList:堆栈管理的网页列表(历史记录)。
-->WKBackForwardListItem:每个网页节点对象。
三,WKWebView属性解析
基本属性
/// webView的自定义配置
@property (nonatomic, readonly, copy)WKWebViewConfiguration*configuration;
/// 导航代理
@property (nonatomic, weak)id<WKNavigationDelegate>navigationDelegate;
/// UI代理
@property ( nonatomic, weak)id <WKUIDelegate> UIDelegate;
/// 自定义初始化webView
- (instancetype)initWithFrame:(CGRect)frame
configuration:(WKWebViewConfiguration *)configuration
- (nullable instancetype)initWithCoder:(NSCoder *)coder
/// 滚动视图
@property (nonatomic, readonly, strong) UIScrollView *scrollView;
加载属性
/// url加载webView视图
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
/// 文件加载webView视图
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL
allowingReadAccessToURL:(NSURL *)readAccessURL
/// HTMLString字符串加载webView视图
- (nullable WKNavigation *)loadHTMLString:(NSString *)string
baseURL:(nullable NSURL *)baseURL;
/// NSData数据加载webView视图
- (nullable WKNavigation *)loadData:(NSData *)data
MIMEType:(NSString *)MIMEType
characterEncodingName:(NSString *)characterEncodingName
baseURL:(NSURL *)baseURL
/// 执行JavaScript
- (void)evaluateJavaScript:(NSString *)javaScriptString
completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
交互控制
/// 访问过网页历史列表
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
/// 返回指定的历史网页
- (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
/// 是否可以返回
@property (nonatomic, readonly) BOOL canGoBack;
/// 是否可以前进
@property (nonatomic, readonly) BOOL canGoForward;
/// 返回到上一个网页
- (nullable WKNavigation *)goBack;
/// 前进到下一个网页
- (nullable WKNavigation *)goForward;
/// 重新加载
- (nullable WKNavigation *)reload;
/// 从初始数据源加载数据,忽略历史记录缓存
- (nullable WKNavigation *)reloadFromOrigin;
/// 停止加载
- (void)stopLoading;
/// 是否允许左右滑动,返回-前进操作 默认是NO
@property (nonatomic) BOOL allowsBackForwardNavigationGestures;
///---目前仅mac支持手势放大,iOS系统不支持---
/// 是否支持放大手势,默认为NO
@property (nonatomic) BOOL allowsMagnification;
/// 放大因子,默认为1
@property (nonatomic) CGFloat magnification;
/// 据设置的缩放因子来缩放页面,并居中显示结果在指定的点
- (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point;
内容与进度,支持KVO模式。
/// 网页的标题
@property (nullable, nonatomic, readonly, copy) NSString *title;
/// 网页的URL地址
@property (nullable, nonatomic, readonly, copy) NSURL *URL;
/// 网页是否正在加载
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
/// 加载的进度 范围为[0, 1]
@property (nonatomic, readonly) double estimatedProgress;
其他
/// 网页链接是否安全
@property (nonatomic, readonly) BOOL hasOnlySecureContent;
/// 证书列表
@property (nonatomic, readonly, copy) NSArray *certificateChain;
/// 证书服务
@property (nonatomic, readonly, nullable) SecTrustRef serverTrust ;
/// 自定义代理字符串
@property (nullable, nonatomic, copy) NSString *customUserAgent ;
/// 在iOS上默认为NO,标识不允许链接预览
@property (nonatomic) BOOL allowsLinkPreview;
四,WKNavigationDelegate协议详解
根据调用顺序注解
// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationActionPolicyCancel);
}
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView
didStartProvisionalNavigation:(WKNavigation *)navigation{
}
// 接收到服务器跳转请求之后调用,主机地址被重定向时调用
- (void)webView:(WKWebView *)webView
didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
}
// 在收到服务器响应后,决定是否跳转
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse
decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
//允许跳转
decisionHandler(WKNavigationResponsePolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationResponsePolicyCancel);
}
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView
didCommitNavigation:(WKNavigation *)navigation{
}
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView
didFinishNavigation:(WKNavigation *)navigation{
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView
didFailProvisionalNavigation:(WKNavigation *)navigation{
}
五,WKUIDelegate协议详解
// 输入框
- (void)webView:(WKWebView *)webView
runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt
defaultText:(nullable NSString *)defaultText
initiatedByFrame:(WKFrameInfo *)frame
completionHandler:(void (^)(NSString * __nullable result))completionHandler{
[[[UIAlertView alloc] initWithTitle:@"输入框"
message:prompt
delegate:nil
cancelButtonTitle:@"确认"
otherButtonTitles: nil] show];
completionHandler(@"你是谁!");
}
// 确认框
- (void)webView:(WKWebView *)webView
runJavaScriptConfirmPanelWithMessage:(NSString *)message
initiatedByFrame:(WKFrameInfo *)frame
completionHandler:(void (^)(BOOL result))completionHandler{
[[[UIAlertView alloc] initWithTitle:@"确认框"
message:message
delegate:nil
cancelButtonTitle:@"确认"
otherButtonTitles: nil] show];
completionHandler(YES);
}
// 警告框
- (void)webView:(WKWebView *)webView
runJavaScriptAlertPanelWithMessage:(NSString *)message
initiatedByFrame:(WKFrameInfo *)frame
completionHandler:(void (^)(void))completionHandler{
[[[UIAlertView alloc] initWithTitle:@"警告框"
message:message
delegate:nil
cancelButtonTitle:@"确认"
otherButtonTitles: nil] show];
completionHandler();
}
// webview关闭时回调
- (void)webViewDidClose:(WKWebView *)webView {
}
// 创建新的webView
// 可以指定配置对象、导航动作对象、window特性。
//如果没用实现这个方法,不会加载链接,如果返回的是原webview会崩溃。
- (nullable WKWebView *)webView:(WKWebView *)webView
createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
forNavigationAction:(WKNavigationAction *)navigationAction
windowFeatures:(WKWindowFeatures *)windowFeatures{
}
当用户在当前页面点击新的跳转链接时,会首先调用WKNavigationDelegate协议中的
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse
decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
WKFrameInfo *sFrame = navigationAction.sourceFrame;//navigationAction的出处
WKFrameInfo *tFrame = navigationAction.targetFrame;//navigationAction的目标
//只有当 tFrame.mainFrame == NO;时,表明这个 WKNavigationAction 将会新开一个页面。
//此时会调用上面的方法,创建一个新的webview来加载新的链接(如果有必要);
}
如果只是打开一个新的地址,为此创建一个新的对象会消耗不必要的资源,所以此时可以在该协议方法中写入以下代码,在当前对象中加载新界面。
WKFrameInfo *frameInfo = navigationAction.targetFrame;
if (![frameInfo isMainFrame]) {
[webView loadRequest:navigationAction.request];
}
return nil;
网友评论