WKWebView基本使用

Starting in iOS 8.0 and OS X 10.10, use WKWebView to add web content to your app. Do not use UIWebView or WebView.

WKWebView新特性

  • 占用內存變少了(模擬器加載百度首頁,WKWebView占用22M,UIWebView占用65M)
  • 更多的支持HTML5的特性
  • 官方宣稱高達60fps的滾動刷新率以及內置手勢
  • 和Safari相同的JavaScript引擎

WKWebView生命周期和跳轉代理

#pragma mark - WKNavigationDelegate
// 頁面開始加載時調用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
    NSLog(@"頁面開始加載:%s",__FUNCTION__);
}
// 當內容開始返回時調用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
    NSLog(@"內容開始返回:%s",__FUNCTION__);
}
// 頁面加載完成之后調用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    NSLog(@"頁面加載完成:%s",__FUNCTION__);
}

// 頁面加載失敗時調用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"%@",error.debugDescription);
}

// 接收到服務器跳轉請求之后調用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
    
}
// 在收到響應后,決定是否跳轉
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    
    NSLog(@"%@",navigationResponse.response.URL.absoluteString);
    //允許跳轉
    decisionHandler(WKNavigationResponsePolicyAllow);
    //不允許跳轉
    //decisionHandler(WKNavigationResponsePolicyCancel);
}
// 在發送請求之前,決定是否跳轉
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    
    NSLog(@"%@",navigationAction.request.URL.absoluteString);
    //允許跳轉
    decisionHandler(WKNavigationActionPolicyAllow);
    //不允許跳轉
    //decisionHandler(WKNavigationActionPolicyCancel);
}

前進 后退 刷新 進度條

//前進
webView.goBack()
//后退
webView.goForward()
//刷新
let request = NSURLRequest(URL:webView.URL!)
webView.loadRequest(request)

//監聽是否可以前進后退,修改btn.enable屬性
webView.addObserver(self, forKeyPath: "loading", options: .New, context: nil)
//監聽加載進度
webView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil)

//重寫self的kvo方法
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if (keyPath == "loading") {
        gobackBtn.enabled = webView.canGoBack
        forwardBtn.enabled = webView.canGoForward
    }
    if (keyPath == "estimatedProgress") {
        //progress是UIProgressView
        progress.hidden = webView.estimatedProgress==1
        progress.setProgress(Float(webView.estimatedProgress), animated: true)
    }
}

JS中alert攔截

在WKWebview中,js的alert是不會出現任何內容的,你必須重寫WKUIDelegate委托的runJavaScriptAlertPanelWithMessage message方法,自己處理alert。類似的還有Confirm和prompt,這里我只以alert為例。

// 輸入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
    completionHandler(@"hello");
}
// 確認框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
    completionHandler(YES);
}
// 警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:webView.title message:message preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }]];
    [self presentViewController:alert animated:YES completion:nil];
}

app調用js方法

WKWebView調用js方法和UIWebView類似,一個是evaluateJavaScript,一個是stringByEvaluatingJavaScriptFromString。獲取返回值的方式不同,WKWebView用的是回調函數獲取返回值。

 //直接調用js
    webView.evaluateJavaScript("hello()", completionHandler: nil)
    //調用js帶參數
    webView.evaluateJavaScript("hello('ls')", completionHandler: nil)
    //調用js獲取返回值
    webView.evaluateJavaScript("getName()") { (any,error) -> Void in
        NSLog("%@", any as! String)
    }

js調用app方法

1:注冊handler需要在webView初始化之前;

   //配置環境
    WKWebViewConfiguration *conf = [[WKWebViewConfiguration alloc] init];
    userContentController = [[WKUserContentController alloc] init];
    conf.userContentController = userContentController;
    
    // 注冊方法
    [userContentController addScriptMessageHandler:self name:@"webViewHandle"];
    
    // 初始化
    self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:conf];

2:處理handler委托。ViewController實現WKScriptMessageHandler委托的方法

// 使用safari模擬器調試
// 前端需要用 window.webkit.messageHandlers.注冊的方法名.postMessage({body:傳輸的數據} 來給native發送消息
// window.webkit.messageHandlers.webViewHandle.postMessage("Hello WebKit!")
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"%@ -- %@",message.name, message.body);
}

3:通過 window.webkit.messageHandlers.webViewApp找到之前注冊的handler對象,然后調用postMessage方法把數據傳到app,app通過上一步的方法從message.body中解析方法名和參數

// 只能傳一個參數 可以用json或字典組裝參數,在app里去解析
var message = 'Hello WebKit!'  
   window.webkit.messageHandlers.webViewApp.postMessage(message);

參考文章

這里僅僅簡要記錄了基本用法。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 隨說 : 最近有個需求,是將公司的一個內網的頁面嵌套在app中作為一個模塊.這不是很簡單的webView請求一下就...
    travin閱讀 30,911評論 26 73
  • 為何使用WKWebView App開發過程中不可避免的會用到加載網頁,從iOS2開始,我們一直使用的是UIWebV...
    辰牧殤閱讀 1,012評論 0 1
  • 前言 關于UIWebView的介紹,相信看過上文的小伙伴們,已經大概清楚了吧,如果有問題,歡迎提問。 本文是本系列...
    CoderLF閱讀 9,010評論 2 12
  • 現在大部分的app只支持iOS8以上的系統了,在接入H5時可以只管最新的WKWebView了。 WKWebView...
    L小杰閱讀 17,327評論 6 33
  • WKWebView 是蘋果在 WWDC 2014 上推出的新一代 webView 組件,用以替代 UIKit 中笨...
    Aiana閱讀 4,621評論 1 8