WKWebView的使用與JS交互詳細解讀


前言

    WKWebView 這是在iOS8.0之后增加的一個比UIWebView更加完善和強大的控件!看網上關於它的博客也是有許多的了,從各個方面總結一下這個WKWebView看網上說它主要是為了和JS做好交互產生的,我們也會相應的嘗試一下。就先從它基本的說起!

一:和UIWebView相比它的不同處

1:和JS更好的做交互,也支持H5的一些新特性

2:加載進度條(下面會演示)

3:性能高,加載變得更快更可靠

二:從加載一張網頁開始

1:使用這個WKWebView是要#import <WebKit/WebKit.h>

2:遵守協議,WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler(最后這個協議留神一下就知道視為JS准備的)

3:加載百度試一下

WKWebView * webviwe = [[WKWebView alloc]initWithFrame:self.view.bounds];
[webviwe loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];
[self.view addSubview:webviwe];    

 

 

三:說說加載進度條

       這個是利用KVO模式寫的,WKWebView有一個  estimatedProgress 屬性,利用它來監聽加載的進度,下面的進度打印出來了,但具體的進度條就沒有寫出來,你們可以自己寫一個 UIProgressView 放在導航欄的下面。

 // estimatedProgress  WKWebView 這個屬性添加觀察者
 [webviwe addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];    

 

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    if (object == webviwe && [keyPath isEqualToString:@"estimatedProgress"] ) {
        // 這里就不寫進度條了,把加載的進度打印出來,進度條可以自己加上去!
        CGFloat newProgress = [[change objectForKey:NSKeyValueChangeNewKey] floatValue];
        NSLog(@"%f",newProgress);  
    }
}

看看打印的進度信息 

2016-08-11 14:44:17.237 RaectiveCocoaTest[21054:252565] 頁面開始加載

2016-08-11 14:44:17.724 RaectiveCocoaTest[21054:252565] 0.300000

2016-08-11 14:44:17.726 RaectiveCocoaTest[21054:252565] 內容正在加載當中

2016-08-11 14:44:18.000 RaectiveCocoaTest[21054:252565] 0.719984

2016-08-11 14:44:18.196 RaectiveCocoaTest[21054:252565] 1.000000

2016-08-11 14:44:18.196 RaectiveCocoaTest[21054:252565] 頁面加載完成

四:詳細的方法使用說明以及注釋

詳解 WKNavigationDelegate 代理方法,我們把它的代理方法使用代碼以及注意點全都寫出來,注意看下面的注釋!

 

#pragma mark - WKNavigationDelegate
// 頁面加載開始  Provisional臨時的
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
{
    NSLog(@"頁面開始加載");   
}
// 加載內容
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
{
    NSLog(@"內容正在加載當中");
}
// 頁面加載完成
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    NSLog(@"頁面加載完成");
}
//  頁面加載失敗
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
{
    NSLog(@"頁面加載失敗");
}
// 接收到服務器重新配置請求之后再執行
-(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
{
    
}
// API是根據WebView對於即將跳轉的HTTP請求頭信息和相關信息來決定是否跳轉
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{   
    NSURLRequest * request = navigationAction.request;
    NSLog(@"%@",request.URL.absoluteString);
    
    // 判斷請求頭是否是 https://www.baidu.com 如果是就不在請求加載跳轉
    WKNavigationActionPolicy  actionPolicy = WKNavigationActionPolicyAllow;
    if ([request.URL.absoluteString hasPrefix:@"https://www.baidu.com"]) {
        
        actionPolicy = WKNavigationActionPolicyCancel;
        
    }
    // 必須這樣執行,不然會崩
    decisionHandler(actionPolicy);
}
/**
 *   
 要是允許跳轉,看下面的打印內容,注意加載的順序!和下面的方法進行比較,區分它們的不同之處
 2016-08-11 13:55:12.628 RaectiveCocoaTest[18155:211964] https://www.baidu.com/
 2016-08-11 13:55:12.629 RaectiveCocoaTest[18155:211964] 頁面開始加載
 2016-08-11 13:55:13.725 RaectiveCocoaTest[18155:211964] 內容正在加載當中
 2016-08-11 13:55:14.681 RaectiveCocoaTest[18155:211964] 頁面加載完成
 *
 */
// API是根據客戶端受到的服務器響應頭以及response相關信息來決定是否可以跳轉
-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
    NSLog(@"%@",navigationResponse.response);
    /**
     *  判斷響應的數據里面的URL是https://www.baidu.com/開頭的,要是就不讓它加載跳轉
     */
    WKNavigationResponsePolicy responsePolicy = WKNavigationResponsePolicyAllow;
    if ([navigationResponse.response.URL.absoluteString hasPrefix:@"https://www.baidu.com/"]) {
        
        responsePolicy = WKNavigationResponsePolicyCancel;
    }
    decisionHandler(responsePolicy);
}
/**
 *  
 響應返回的的URL包含了https://www.baidu.com/,所以頁面是不能被加載的,要是能加載就有下面的打印信息,注意和上面方法的區分對比!
 2016-08-11 13:53:38.392 RaectiveCocoaTest[17961:209778] 頁面開始加載
 2016-08-11 13:53:38.675 RaectiveCocoaTest[17961:209778] https://www.baidu.com/
 2016-08-11 13:53:38.678 RaectiveCocoaTest[17961:209778] 內容正在加載當中
 2016-08-11 13:53:38.936 RaectiveCocoaTest[17961:209778] 頁面加載完成
 */

 五:說說WKUIDelegate和JS的簡單交互 

先看看 WKUIDelegate里面的代理方法都是用來做什么的,我們一個一個的解釋這幾個代理方法;

// 創建方法,這個就不在多說了,重點放在下面幾個
-(nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
{
    return nil;
}

// ios 9 之后才有的方法
-(void)webViewDidClose:(WKWebView *)webView
{
    
}

下面這三個方法根據方法前面的字面意思就能區分記住!

runJavaScriptAlert 方法注意點

1.在JS端調用alert函數時,會觸發此代理方法。

2.JS端調用alert時所傳的數據可以通過message,打印message信息讀取出JS端給你的信息。

3.在原生得到結果后,需要回調給JS,通過completionHandler 回調給JS

4.completionHandler 回調的參數和返回值都是空

/**
下面這三個方法根據前面的字面意思就能區分記住!
 */
// runJavaScriptAlert
// 在JS端調用alert函數時,會觸發此代理方法。
// JS端調用alert時所傳的數據可以通過message,打印message信息讀取出JS端給你的信息。
// 在原生得到結果后,需要回調給JS,通過completionHandler 回調給JS
// completionHandler 回調的參數和返回值都是空
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"alert"message:@"JS調用alert"preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
    }]];
    
    [self presentViewController:alert animated:YES completion:NULL];
    NSLog(@"%@", message);
    
}

runJavaScriptTextInput 注意點

1.要求用戶輸入一段文字

3.在原生輸入得到文本內容后,通過completionHandler回調給JS

4.大家注意這個回調的completionHandler參數是字符串 

// runJavaScriptTextInput
// 要求用戶輸入一段文本
// 在原生輸入得到文本內容后,通過completionHandler回調給JS 大家注意這個回調的completionHandler參數是字符串
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler
{

}

runJavaScriptConfirmPane(ConfirmPane字面意思是確認框)

1.JS端調用confirm函數時,會觸發此方法

2.通過message可以拿到JS端所傳給我們數據

3.在iOS端顯示原生alert得到YES/NO后,通過completionHandler回調給JS端

4.注意這個completionHandler回調的參數是BOOL類型的

-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler
{
    
}

要有什么問題或者發現錯誤的地方,及時留言聯系我,立馬改正!  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM