WKWebView學習筆記

一、簡介

webView是我們日常開發中不可缺少的一個組件,通常我們都是使用UIWebView來實現的,不過大多數情況下,UIWebView的表現卻不盡如人意(最直觀的就是內存消耗嚴重,特別是有視頻的時候,有木有!)
iOS8之后蘋果推薦使用WKWebView替代UIWebView,其主要的有點有:

  1. 在性能、穩定性
  2. WKWebView更多的支持HTML5的特性
  3. WKWebView更快,占用內存可能只有UIWebView的1/3 ~ 1/4
  4. WKWebView高達60fps的滾動刷新率和豐富的內置手勢
  5. WKWebView具有Safari相同的JavaScript引擎
  6. WKWebView增加了加載進度屬性
  7. 將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.lxweimin.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的新特性與使用

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,996評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,316評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,406評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,128評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,524評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,759評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,310評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,065評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,249評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,479評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,909評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,140評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,984評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,228評論 2 375

推薦閱讀更多精彩內容