WKWebView學習筆記
一、簡介
webView是我們日常開發中不可缺少的一個元件,通常我們都是使用UIWebView來實現的,不過大多數情況下,UIWebView的表現卻不盡如人意(最直觀的就是記憶體消耗嚴重,特別是有視訊的時候,有木有!)
iOS8之後蘋果推薦使用WKWebView替代UIWebView,其主要的有點有:
- 在效能、穩定性
- WKWebView更多的支援HTML5的特性
- WKWebView更快,佔用記憶體可能只有UIWebView的1/3 ~ 1/4
- WKWebView高達60fps的滾動重新整理率和豐富的內建手勢
- WKWebView具有Safari相同的JavaScript引擎
- WKWebView增加了載入進度屬性
- 將UIWebViewDelegate和UIWebView重構成了14個類與3個協議官方連結
Classes:
- WKBackForwardList: 之前訪問過的 web 頁面的列表,可以通過後退和前進動作來訪問到。
- WKBackForwardListItem: webview 中後退列表裡的某一個網頁。
- WKFrameInfo: 包含一個網頁的佈局資訊。
- WKNavigation: 包含一個網頁的載入進度資訊。
- WKNavigationAction: 包含可能讓網頁導航變化的資訊,用於判斷是否做出導航變化。
- WKNavigationResponse: 包含可能讓網頁導航變化的返回內容資訊,用於判斷是否做出導航變化。
- WKPreferences: 概括一個 webview 的偏好設定。
- WKProcessPool: 表示一個 web 內容載入池。
- WKUserContentController: 提供使用 JavaScript post 資訊和注射 script 的方法。
- WKScriptMessage: 包含網頁發出的資訊。
- WKUserScript: 表示可以被網頁接受的使用者指令碼。
- WKWebViewConfiguration: 初始化 webview 的設定。
- WKWindowFeatures: 指定載入新網頁時的視窗屬性。
Protocols
- WKNavigationDelegate: 提供了追蹤主視窗網頁載入過程和判斷主視窗和子視窗是否進行頁面載入新頁面的相關方法。
- WKScriptMessageHandler: 提供從網頁中收訊息的回撥方法。
- WKUIDelegate: 提供用原生控制元件顯示網頁的方法回撥。
廢話了這麼多,用一個剛剛測試過的圖來展示下記憶體優化了

WKWebView載入視訊.png

UIWebView載入視訊.png
差距了幾倍的記憶體。下面就聊聊WKWebView的使用。
二、簡單使用
1.首先自然是匯入標頭檔案(iOS9之後預設不支援HTTP協議,別忘了在Info.plist裡面新增支援)
#import<WebKit/WebKit.h>
2.初始化

(1)由於WKWebView的父類是UIView,所以可以用我們最常用的方法來初始化:
WKWebView *webView = [[WKWebView alloc]initWithFrame:self.view.frame];
(2)WKWebView自己也具備一個自己的初始化方法
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration*)configuration
這裡面WKWebViewConfiguration就是一個上面講述的重構了類中的一個,負責的內容是:
A WKWebViewConfiguration object is a collection of properties used to initialize a web view.
WKWebViewConfiguration 是一個屬性的集合 用來初始化web檢視。
這個類包含眾多的屬性,預知詳情請見官方文件,這裡介紹幾個常用的屬性(偏好的設定):
//初始化一個WKWebViewConfiguration物件 WKWebViewConfiguration *config = [WKWebViewConfiguration new]; //初始化偏好設定屬性:preferences config.preferences = [WKPreferences new]; //The minimum font size in points default is 0; config.preferences.minimumFontSize = 10; //是否支援JavaScript config.preferences.javaScriptEnabled = YES; //不通過使用者互動,是否可以開啟視窗 config.preferences.javaScriptCanOpenWindowsAutomatically = NO; WKWebView *webView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:config]; [self.view addSubview:webView];
3.載入網頁
最基礎的方法和UIWebView一樣
NSURL *url = [NSURL URLWithString:@"www.jianshu.com"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [webView loadRequest:request];
這裡有幾個載入的方法:
//載入本地URL檔案 - (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL //載入本地HTML字串 - (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL; //載入二進位制資料 - (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL
每個方法都會返回一個WKNavigation物件,官方介紹是
一個WKNavigation物件包含資訊跟蹤載入一個網頁的進展。
A WKNavigation object contains information for tracking the loading progress of a webpage.
導航web檢視載入方法返回的物件,也是傳遞到導航委託方法來唯一地標識一個網頁載入從開始到結束。它沒有自己的方法或屬性。
A navigation object is returned from the web view load methods and is also passed to the navigation delegate methods to uniquely identify a webpage load from start to finish. It has no method or properties of its own.
然後我建立了兩個WKWebView,載入同樣的url,列印的結果是不同的地址:

這個屬性在WKWebView的代理方法裡面有用到,我的理解就是用來標記不同的webView的。
三、所有相關的類的API
這裡的東西比較多,想看一些高階使用的直接跳過看下一節,或者直接下載 Demo
1.WKWebView
//上文介紹過的偏好配置 @property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration; // 導航代理 @property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate; // 使用者互動代理 @property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate; // 頁面前進、後退列表 @property (nonatomic, readonly, strong) WKBackForwardList *backForwardList; // 預設構造器 - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER; //載入請求API - (nullable WKNavigation *)loadRequest:(NSURLRequest *)request; // 載入URL - (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL NS_AVAILABLE(10_11, 9_0); // 直接載入HTML - (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL; // 直接載入data - (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL NS_AVAILABLE(10_11, 9_0); // 前進或者後退到某一頁面 - (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item; // 頁面的標題,支援KVO的 @property (nullable, nonatomic, readonly, copy) NSString *title; // 當前請求的URL,支援KVO的 @property (nullable, nonatomic, readonly, copy) NSURL *URL; // 標識當前是否正在載入內容中,支援KVO的 @property (nonatomic, readonly, getter=isLoading) BOOL loading; // 當前載入的進度,範圍為[0, 1] @property (nonatomic, readonly) double estimatedProgress; // 標識頁面中的所有資源是否通過安全加密連線來載入,支援KVO的 @property (nonatomic, readonly) BOOL hasOnlySecureContent; // 當前導航的證書鏈,支援KVO @property (nonatomic, readonly, copy) NSArray *certificateChain NS_AVAILABLE(10_11, 9_0); // 是否可以招待goback操作,它是支援KVO的 @property (nonatomic, readonly) BOOL canGoBack; // 是否可以執行gofarward操作,支援KVO @property (nonatomic, readonly) BOOL canGoForward; // 返回上一頁面,如果不能返回,則什麼也不幹 - (nullable WKNavigation *)goBack; // 進入下一頁面,如果不能前進,則什麼也不幹 - (nullable WKNavigation *)goForward; // 重新載入頁面 - (nullable WKNavigation *)reload; // 重新從原始URL載入 - (nullable WKNavigation *)reloadFromOrigin; // 停止載入資料 - (void)stopLoading; // 執行JS程式碼 - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler; // 標識是否支援左、右swipe手勢是否可以前進、後退 @property (nonatomic) BOOL allowsBackForwardNavigationGestures; // 自定義user agent,如果沒有則為nil @property (nullable, nonatomic, copy) NSString *customUserAgent NS_AVAILABLE(10_11, 9_0); // 在iOS上預設為NO,標識不允許連結預覽 @property (nonatomic) BOOL allowsLinkPreview NS_AVAILABLE(10_11, 9_0); #if TARGET_OS_IPHONE /*! @abstract The scroll view associated with the web view. */ @property (nonatomic, readonly, strong) UIScrollView *scrollView; #endif #if !TARGET_OS_IPHONE // 標識是否支援放大手勢,預設為NO @property (nonatomic) BOOL allowsMagnification; // 放大因子,預設為1 @property (nonatomic) CGFloat magnification; // 根據設定的縮放因子來縮放頁面,並居中顯示結果在指定的點 - (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point; #endif
2. WKPreferences偏好設定
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; // 設定偏好設定 config.preferences = [[WKPreferences alloc] init]; // 預設為0 config.preferences.minimumFontSize = 10; // 預設認為YES config.preferences.javaScriptEnabled = YES; // 在iOS上預設為NO,表示不能自動通過視窗開啟 config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
3.WKProcessPool內容處理池
這個類沒有公開的方法和屬性,而且也並不需要配置,可以暫時忽略。
4. WKUserContentController內容互動控制器
我們要通過JS與webview內容互動,就需要到這個類了,它的所有屬性及方法說明如下:
// 只讀屬性,所有新增的WKUserScript都在這裡可以獲取到 @property (nonatomic, readonly, copy) NSArray<WKUserScript *> *userScripts; // 注入JS - (void)addUserScript:(WKUserScript *)userScript; // 移除所有注入的JS - (void)removeAllUserScripts; // 新增scriptMessageHandler到所有的frames中,則都可以通過 // window.webkit.messageHandlers.<name>.postMessage(<messageBody>) // 傳送訊息 // 比如,JS要呼叫我們原生的方法,就可以通過這種方式了 - (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name; // 根據name移除所注入的scriptMessageHandler - (void)removeScriptMessageHandlerForName:(NSString *)name;
5. WKUserScript
在WKUserContentController中,所有使用到WKUserScript。WKUserContentController是用於與JS互動的類,而所注入的JS是WKUserScript物件。它的所有屬性和方法如下:
// JS原始碼 @property (nonatomic, readonly, copy) NSString *source; // JS注入時間 @property (nonatomic, readonly) WKUserScriptInjectionTime injectionTime; // 只讀屬性,表示JS是否應該注入到所有的frames中還是隻有main frame. @property (nonatomic, readonly, getter=isForMainFrameOnly) BOOL forMainFrameOnly; // 初始化方法,用於建立WKUserScript物件 // source:JS原始碼 // injectionTime:JS注入的時間 // forMainFrameOnly:是否只注入main frame - (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;
6.WKWebsiteDataStore儲存的Web內容
iOS9.0以後才能使用這個類。是代表webView不同的資料型別,cookies、disk、memory caches、WebSQL、IndexedDB資料庫和本地儲存。版本適配的化就要放棄了。
// 預設資料儲存 + (WKWebsiteDataStore *)defaultDataStore; // 返回非持久化儲存,資料不會寫入檔案系統 + (WKWebsiteDataStore *)nonPersistentDataStore; // 只讀屬性,表示是否是持久化儲存 @property (nonatomic, readonly, getter=isPersistent) BOOL persistent; // 獲取所有web內容的資料儲存型別集,比如cookies、disk等 + (NSSet<NSString *> *)allWebsiteDataTypes; // 獲取某些指定資料儲存型別的資料 - (void)fetchDataRecordsOfTypes:(NSSet<NSString *> *)dataTypes completionHandler:(void (^)(NSArray<WKWebsiteDataRecord *> *))completionHandler; // 刪除某些指定型別的資料 - (void)removeDataOfTypes:(NSSet<NSString *> *)dataTypes forDataRecords:(NSArray<WKWebsiteDataRecord *> *)dataRecords completionHandler:(void (^)(void))completionHandler; // 刪除某些指定型別的資料且修改日期是指定的日期 - (void)removeDataOfTypes:(NSSet<NSString *> *)websiteDataTypes modifiedSince:(NSDate *)date completionHandler:(void (^)(void))completionHandler;
7. WKWebsiteDataRecord
同樣 iOS9.0 之後可以使用,website的資料儲存記錄型別,它只有兩個屬性:
// 通常是域名 @property (nonatomic, readonly, copy) NSString *displayName; // 儲存的資料型別集 @property (nonatomic, readonly, copy) NSSet<NSString *> *dataTypes;
8. WKNavigationDelegate
@protocol WKNavigationDelegate <NSObject> @optional // 決定導航的動作,通常用於處理跨域的連結能否導航。WebKit對跨域進行了安全檢查限制,不允許跨域,因此我們要對不能跨域的連結 // 單獨處理。但是,對於Safari是允許跨域的,不用這麼處理。 // 這個是決定是否Request - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler; // 決定是否接收響應 // 這個是決定是否接收response // 要獲取response,通過WKNavigationResponse物件獲取 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler; // 當main frame的導航開始請求時,會呼叫此方法 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation; // 當main frame接收到服務重定向時,會回撥此方法 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation; // 當main frame開始載入資料失敗時,會回撥 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error; // 當main frame的web內容開始到達時,會回撥 - (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation; // 當main frame導航完成時,會回撥 - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation; // 當main frame最後下載資料失敗時,會回撥 - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error; // 這與用於授權驗證的API,與AFN、UIWebView的授權驗證API是一樣的 - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *__nullable credential))completionHandler; // 當web content處理完成時,會回撥 - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0); @end
9. WKNavigationResponse
WKNavigationResponse是導航響應類,通過它可以獲取相關響應的資訊:
NS_CLASS_AVAILABLE(10_10, 8_0) @interface WKNavigationResponse : NSObject // 是否是main frame @property (nonatomic, readonly, getter=isForMainFrame) BOOL forMainFrame; // 獲取響應response @property (nonatomic, readonly, copy) NSURLResponse *response; // 是否顯示MIMEType @property (nonatomic, readonly) BOOL canShowMIMEType; @end
10. WKNavigationAction
WKNavigationAction物件包含關於導航的action的資訊,用於make policy decisions。它只有以下幾個屬性:
// 正在請求的導航的frame @property (nonatomic, readonly, copy) WKFrameInfo *sourceFrame; // 目標frame,如果這是新的window,它會是nil @property (nullable, nonatomic, readonly, copy) WKFrameInfo *targetFrame; // 導航型別,如下面的小標題WKNavigationType @property (nonatomic, readonly) WKNavigationType navigationType; // 導航的請求 @property (nonatomic, readonly, copy) NSURLRequest *request;
11. WKUIDelegate
@protocol WKUIDelegate <NSObject> @optional // 建立新的webview // 可以指定配置物件、導航動作物件、window特性 - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures; // webview關閉時回撥 - (void)webViewDidClose:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0); // 呼叫JS的alert()方法 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler; // 呼叫JS的confirm()方法 - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler; // 呼叫JS的prompt()方法 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler; @end
12. WKBackForwardList
WKBackForwardList表示webview中可以前進或者後退的頁面列表。其宣告如下:
NS_CLASS_AVAILABLE(10_10, 8_0) @interface WKBackForwardList : NSObject // 當前正在顯示的item(頁面) @property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *currentItem; // 後一頁,如果沒有就是nil @property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *backItem; // 前一頁,如果沒有就是nil @property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *forwardItem; // 根據下標獲取某一個頁面的item - (nullable WKBackForwardListItem *)itemAtIndex:(NSInteger)index; // 可以進行goback操作的頁面列表 @property (nonatomic, readonly, copy) NSArray<WKBackForwardListItem *> *backList; // 可以進行goforward操作的頁面列表 @property (nonatomic, readonly, copy) NSArray<WKBackForwardListItem *> *forwardList; @end
13. WKBackForwardListItem
頁面導航前進、後退列表項:
NS_CLASS_AVAILABLE(10_10, 8_0) @interface WKBackForwardListItem : NSObject // 該頁面的URL @property (readonly, copy) NSURL *URL; // 該頁面的title @property (nullable, readonly, copy) NSString *title; // 初始請求該item的請求的URL @property (readonly, copy) NSURL *initialURL; @end
四WKWebView與JS實戰
初始化的相關內容在這裡不再贅述,提幾個常常關注的點
1.新增對WKWebView屬性的監聽
這裡面處理一下常用的三個:loading、title、estimatedProgress屬性,分別用於判斷是否正在載入、獲取頁面標題、當前頁面載入進度:
// 新增KVO監聽 [self.webView addObserver:self forKeyPath:@"loading" options:NSKeyValueObservingOptionNew context:nil]; [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil]; [self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
這裡不要忘記在介面消失的時候,移除監聽
[_webView removeObserver:self forKeyPath:@"loading" context:nil];//移除kvo [_webView removeObserver:self forKeyPath:@"title" context:nil]; [_webView removeObserver:self forKeyPath:@"estimatedProgress" context:nil];
KVO方法:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"loading"]) { NSLog(@"loading"); } else if ([keyPath isEqualToString:@"title"]) { self.title = self.webView.title; } else if ([keyPath isEqualToString:@"estimatedProgress"]) { NSLog(@"progress: %f", self.webView.estimatedProgress); self.progressView.progress = self.webView.estimatedProgress; } // 載入完成 if (!self.webView.loading) { [UIView animateWithDuration:0.5 animations:^{ self.progressView.alpha = 0.0; }]; } }
2.配置Js與WebView內容互動
前面提到了WKUserContentController是用於讓Js注入物件的,注入物件後,JS端就可以使用這個方法:
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
用這個方法傳送資料給iOS客戶端,eg:
window.webkit.messageHandlers.senderModel.postMessage({body: 'sender message'});
這裡面senderModel就是我們要注入的名稱,注入之後,就可以在Js端呼叫了,傳資料統一通過body來傳遞,型別可以隨意,但是隻支援OC的一些型別(NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull型別。)
iOS端的部分程式碼:
config.userContentController = [[WKUserContentController alloc] init]; // 注入JS物件名稱senderModel,當JS通過senderModel來呼叫時,我們可以在WKScriptMessageHandler代理中接收到 [config.userContentController addScriptMessageHandler:self name:@"senderModel"]; #pragma mark - WKScriptMessageHandler - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([message.name isEqualToString:@"senderModel"]) { // 列印所傳過來的引數,只支援NSNumber, NSString, NSDate, NSArray, // NSDictionary, and NSNull型別 //do something NSLog(@"%@", message.body); } }
3. WKUIDelegate代理方法
與JS的alert、confirm、prompt互動,我們希望用自己的原生介面,而不是JS的,就可以使用這個代理類來實現。
- alert警告框函式:
//alert 警告框 -(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{ UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"警告" message:@"呼叫alert提示框" preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { completionHandler(); }]]; [self presentViewController:alert animated:YES completion:nil]; NSLog(@"alert message:%@",message); }
- confirm確認框函式:
//confirm 確認框 -(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{ UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"確認框" message:@"呼叫confirm提示框" preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { completionHandler(YES); }]]; [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { completionHandler(NO); }]]; [self presentViewController:alert animated:YES completion:NULL]; NSLog(@"confirm message:%@", message); }
- prompt 輸入框函式:
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler { UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"輸入框" message:@"呼叫輸入框" preferredStyle:UIAlertControllerStyleAlert]; [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.textColor = [UIColor blackColor]; }]; [alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { completionHandler([[alert.textFields lastObject] text]); }]]; [self presentViewController:alert animated:YES completion:NULL]; }
4.WKNavigationDelegate
代理方法在第三節有提到,這裡在重複一下吧
- 用來追蹤載入過程的方法:
//開始載入時呼叫 -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{ } //當內容開始返回時呼叫 -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{ } //頁面載入完成之後呼叫 -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ } // 頁面載入失敗時呼叫 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation { }
- 頁面跳轉的代理方法:
// 接收到伺服器跳轉請求之後呼叫 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; // 在收到響應後,決定是否跳轉 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler; // 在傳送請求之前,決定是否跳轉 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
以上的方法根據實際需求操作即可。
最後
Demo地址: WKWebViewDemo
參考連結: WKWebView的新特性與使用