iOS8之后,蘋果推出了WebKit這個(gè)框架,用來替換原有的UIWebView,這邊簡單的介紹一下WKWebView的使用方法
一、WKWebView新特性
- 在性能、穩(wěn)定性、功能方面有很大提升(最直觀的體現(xiàn)就是加載網(wǎng)頁是占用的內(nèi)存);
- 允許JavaScript的Nitro庫加載并使用(UIWebView中限制);
- 支持了更多的HTML5特性;
- 高達(dá)60fps的滾動(dòng)刷新率以及內(nèi)置手勢;
- 將UIWebViewDelegate與UIWebView重構(gòu)成了14類與3個(gè)協(xié)議查看蘋果官方文檔;
二、WebKit框架概覽

WebKit框架概覽.png
如上圖所示,WebKit框架中最核心的類應(yīng)該屬于WKWebView了,這個(gè)類專門用來渲染網(wǎng)頁視圖,其他類和協(xié)議都將基于它和服務(wù)于它。
- WKWebView:網(wǎng)頁的渲染與展示,通過WKWebViewConfiguration可以進(jìn)行自定義配置。
- WKPreference:這個(gè)類用來進(jìn)行相關(guān)webview 設(shè)置。
- WKProcessPool:這個(gè)類用來配置進(jìn)程池,與網(wǎng)頁視圖的資源共享有關(guān)。
- WKUserContentController:這個(gè)類主要用來做native與JS的交互管理,提供使用JS post 信息和注射 script 的方法。
- WKUserScript:表示可以被網(wǎng)頁接受的用戶JS,用于進(jìn)行JS注入。。
- WKScriptMessageHandler:這個(gè)類專門用來處理JS調(diào)用native的方法,提供從網(wǎng)頁中收消息的回調(diào)方法。
- WKNavigationDelegate: 提供了追蹤主窗口網(wǎng)頁加載過程和判斷主窗口和子窗口是否進(jìn)行頁面加載新頁面的相關(guān)方法。
- WKNavigationAction:網(wǎng)頁某個(gè)活動(dòng)的示例化對(duì)象,包含可能讓網(wǎng)頁導(dǎo)航變化的信息,用于判斷是否做出導(dǎo)航變化。
- WKFrameInfo: 包含一個(gè)網(wǎng)頁的布局信息。
- WKNavigationResponse:包含可能讓網(wǎng)頁導(dǎo)航變化的返回內(nèi)容信息,用于判斷是否做出導(dǎo)航變化。
- WKUIDelegate: 提供用原生控件顯示網(wǎng)頁的方法回調(diào),用于交互處理JavaScript中的一些彈出框。
- WKBackForwardList:之前訪問過的 web頁面的列表,可以通過后退和前進(jìn)動(dòng)作來訪問到。
- WKBackForwardListItem: webview中后退列表里的某一個(gè)網(wǎng)頁。
- WKNavigation: 包含一個(gè)網(wǎng)頁的加載進(jìn)度信息。
- WKScriptMessage: 包含網(wǎng)頁發(fā)出的信息。
- WKWebViewConfiguration: 初始化 webview 的設(shè)置。
- WKWindowFeatures: 指定加載新網(wǎng)頁時(shí)的窗口屬性。
三、WKWebView的屬性
/** webView的自定義配置 */
@property (nonatomic,readonly, copy) WKWebViewConfiguration *configuration;
/** 導(dǎo)航代理 */
@property (nullable, nonatomic, weak)id <WKNavigationDelegate> navigationDelegate;
/** 用戶交互代理 */
@property (nullable, nonatomic, weak)id <WKUIDelegate> UIDelegate;
/** 訪問過網(wǎng)頁歷史列表 */
@property (nonatomic,readonly, strong) WKBackForwardList *backForwardList;
/** 自定義初始化 */
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration;
/** 加載請求API */
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
/** 加載本地URL文件 */
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL;
/** 加載本地html字符串 */
- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
/** NSData數(shù)據(jù)加載webView視圖 */
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL;
/** 返回上一個(gè)網(wǎng)頁節(jié)點(diǎn) */
- (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
/** 網(wǎng)頁的標(biāo)題,支持KVO */
@property (nullable, nonatomic,readonly, copy) NSString *title;
/** 網(wǎng)頁的URL地址,支持KVO */
@property (nullable, nonatomic,readonly, copy) NSURL *URL;
/** 網(wǎng)頁是否正在加載,支持KVO */
@property (nonatomic,readonly, getter=isLoading) BOOL loading;
/** 加載的進(jìn)度 范圍為[0, 1] */
@property (nonatomic,readonly)double estimatedProgress;
/** 網(wǎng)頁鏈接是否安全(標(biāo)識(shí)頁面中的所有資源是否通過安全加密連接來加載),支持KVO */
@property (nonatomic,readonly) BOOL hasOnlySecureContent;
/** 證書服務(wù) */
@property (nonatomic,readonly, nullable) SecTrustRef serverTrust;
/** 是否可以返回,支持KVO */
@property (nonatomic,readonly) BOOL canGoBack;
/** 是否可以前進(jìn),支持KVO */
@property (nonatomic,readonly) BOOL canGoForward;
/** 返回到上一個(gè)網(wǎng)頁,如果不能返回,則什么也不干 */
- (nullable WKNavigation *)goBack;
/** 前進(jìn)到下一個(gè)網(wǎng)頁,如果不能返回,則什么也不干 */
- (nullable WKNavigation *)goForward;
/** 重新加載 */
- (nullable WKNavigation *)reload;
/** 比較網(wǎng)絡(luò)數(shù)據(jù)是否有變化,沒有變化則使用緩存,否則從新請求 */
- (nullable WKNavigation *)reloadFromOrigin;
/** 停止加載 */
- (void)stopLoading;
/** 執(zhí)行JavaScript */
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void(^ _Nullable)(_Nullableid, NSError * _Nullable error))completionHandler;
/** 是否允許左右滑動(dòng),返回-前進(jìn)操作 默認(rèn)是NO */
@property (nonatomic) BOOL allowsBackForwardNavigationGestures;
/** 自定義useragent,如果沒有則為nil */
@property (nullable, nonatomic, copy) NSString *customUserAgent;
/** 在iOS上默認(rèn)為NO,標(biāo)識(shí)不允許鏈接預(yù)覽 */
@property (nonatomic) BOOL allowsLinkPreview;
/** 滾動(dòng)視圖 */
@property (nonatomic,readonly, strong) UIScrollView *scrollView;
/** 是否支持放大手勢,默認(rèn)為NO */
@property (nonatomic) BOOL allowsMagnification;
/** 放大因子,默認(rèn)為1 */
@property (nonatomic) CGFloat magnification;
/** 據(jù)設(shè)置的縮放因子來縮放頁面,并居中顯示結(jié)果在指定的點(diǎn) */
- (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point;
/** 證書列表,支持KVO */
@property (nonatomic,readonly, copy) NSArray *certificateChain;
四、方法使用介紹
(一)初始化
/** 默認(rèn)初始化 */
- (instancetype)init;
- (instancetype)initWithFrame:(CGRect)frame;
/** 根據(jù)對(duì)webview的相關(guān)配置,進(jìn)行初始化 */
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration;
(二)WKWebView代理方法
1、WKNavigationDelegate
- 該代理提供的方法,可以用來追蹤加載過程(頁面開始加載、加載完成、加載失敗)、決定是否執(zhí)行跳轉(zhuǎn)。
/** 頁面開始加載時(shí)調(diào)用 */
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
/** 當(dāng)內(nèi)容開始返回時(shí)調(diào)用 */
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
/** 頁面加載完成之后調(diào)用 */
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
/** 頁面加載失敗時(shí)調(diào)用 */
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
/** 頁面進(jìn)程被終止時(shí)調(diào)用(web總體內(nèi)存占用過大,頁面即將白屏?xí)r) */
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView;
- 頁面跳轉(zhuǎn)的代理有三種,分別為(收到跳轉(zhuǎn)與決定是否跳轉(zhuǎn)兩種)
/** 接收到服務(wù)器跳轉(zhuǎn)請求之后調(diào)用 */
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
/** 在收到響應(yīng)后,決定是否跳轉(zhuǎn) */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
/** 在發(fā)送請求之前,決定是否跳轉(zhuǎn) */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
/** web驗(yàn)證證書時(shí)調(diào)用(https加載要調(diào)用) */
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void(^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;
2、WKUIDelegate
- 以下三個(gè)代理都是與界面彈出提示框相關(guān),分別針對(duì)web界面的三種提示框(警告框、確認(rèn)框、輸入框)的代理,如果不實(shí)現(xiàn)網(wǎng)頁的alert函數(shù)無效
/**
* web界面中有彈框時(shí)調(diào)用
* @param webView 實(shí)現(xiàn)該代理的webview
* @param message alert框中的內(nèi)容
* @param frame 主窗口
* @param completionHandler alert框消失時(shí)調(diào)用
* @param prompt alert框中的內(nèi)容
* @param defaultText 輸入框中默認(rèn)要輸入文本的提示
*/
/** 警告框 【對(duì)應(yīng)JS的Alert方法】 */
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
/** 選擇框 【對(duì)應(yīng)JS的confirm方法】 */
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler;
/** 輸入框 【對(duì)應(yīng)JS的prompt方法】 */
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler;
- 以下代理是和窗口相關(guān)
/** 創(chuàng)建新的webview時(shí)調(diào)用(打開新窗口) */
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
/** 成功關(guān)閉webview時(shí)調(diào)用 */
- (void)webViewDidClose:(WKWebView *)webView;
- 下面這些方法是交互JavaScript的方法
/** JavaScript調(diào)用confirm方法后回調(diào)的方法 confirm是js中的確定框,需要在block中把用戶選擇的情況傳遞進(jìn)去 */
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(BOOL))completionHandler;
/** JavaScript調(diào)用prompt方法后回調(diào)的方法 prompt是js中的輸入框 需要在block中把用戶輸入的信息傳入 */
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(NSString * _Nullable))completionHandler;
/** 確認(rèn)是否顯示預(yù)覽(默認(rèn)預(yù)覽元素調(diào)用) */
- (BOOL)webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo;
/** 執(zhí)行預(yù)覽操作時(shí)調(diào)用(返回一個(gè)視圖控制器將導(dǎo)致視圖控制器被顯示為一個(gè)預(yù)覽。返回nil將WebKit的默認(rèn)預(yù)覽的行為。) */
- (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray> *)previewActions;
/** 當(dāng)用戶在預(yù)覽中執(zhí)行彈出操作時(shí)調(diào)用(允許應(yīng)用程序向它創(chuàng)建的視圖控制器彈出) */
- (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController;
/** 顯示一個(gè)文件上傳面板。(completionhandler完成處理程序調(diào)用后打開面板已被撤銷。通過選擇的網(wǎng)址,如果用戶選擇確定,否則為零。如果不實(shí)現(xiàn)此方法,Web視圖將表現(xiàn)為如果用戶選擇了取消按鈕。) */
- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(NSArray * _Nullable URLs))completionHandler;
3、WKScriptMessageHandler
- 這個(gè)協(xié)議中包含一個(gè)必須實(shí)現(xiàn)的方法,這個(gè)方法是提高App與web端交互的關(guān)鍵,它可以直接將接收到的JS腳本轉(zhuǎn)化為OC或Swift對(duì)象。(當(dāng)然,在UIWebView也可以通過“曲線救國”的方式與web進(jìn)行交互,著名的Cordova框架就是這種機(jī)制)
/** 從web界面中接收到一個(gè)腳本時(shí)調(diào)用 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
參考:
獨(dú)木舟的木的簡書 - WKWebView
侭情顯現(xiàn)的簡書 - WKWebView的小使用
玄冰優(yōu)的個(gè)人圖書館 - iOS開發(fā) WKWebView學(xué)習(xí)使用
_Ace的博客 - WKWebView使用
袁夢龍的博客 - WKWebView 的使用和踩過的坑