WKWebView基本使用

一、基本的使用方法

<p>介紹:
? ? ? ?WKWebView是蘋果推出的框架,性能比UIWebView更優。
首先上DEMO

WKWebView有兩個delegate,WKUIDelegateWKNavigationDelegate

WKNavigationDelegate主要處理一些跳轉、加載處理操作,

WKUIDelegate主要處理JS腳本,確認框,警告框等。因此WKNavigationDelegate更加常用。</p>

    // 1.配置環境
    WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
    userContentController =[[WKUserContentController alloc]init];
    configuration.userContentController = userContentController;
    wkWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) configuration:configuration];
    
    // 2.注冊方法(必要設置,不然WKWebView會無法釋放)
    WKDelegateController * delegateController = [[WKDelegateController alloc]init];
    delegateController.delegate = self;
    // 有添加一定有移除,成對出現
    [userContentController addScriptMessageHandler:delegateController  name:@"NativeMethod"];
    
    [self.view addSubview:wkWebView];
    
    wkWebView.UIDelegate = self;
    wkWebView.navigationDelegate = self;
    
    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
    // 根據URL創建請求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setTimeoutInterval:15];
    [wkWebView loadRequest:request];

常用的代理方法

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{

        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);
    }

WKUIDelegate

    // 創建一個新的WebView
    -(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{

        return [[WKWebView alloc]init];
    }

    // 輸入框
    -(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{

        completionHandler(@"http");
    }

    // 確認框
    -(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{

        NSLog(@"%@",message);
        completionHandler();
    }

    -(void)dealloc{

        //這里需要注意,前面增加過的方法一定要remove掉。
        [userContentController removeScriptMessageHandlerForName:@"NativeMethod"];
    }

WKScriptMessageHandler

    -(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

        NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
    }


// 創建新的控制器設置代理(解決不能釋放的問題)
    @protocol WKDelegate <NSObject><br>
    -(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
    @end

    @interface WKDelegateController : UIViewController <WKScriptMessageHandler>
    @property (weak , nonatomic) id<WKDelegate> delegate;
    @end

    .m文件中的實現

    -(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

        if ([self.delegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
            [self.delegate userContentController:userContentController didReceiveScriptMessage:message];
        }
    }

關于session 同步 cookies的問題

#### 1.基本配置
    NSMutableString *cookies = [NSMutableString string];
    WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[cookies copy]
                                                         injectionTime:WKUserScriptInjectionTimeAtDocumentStart
                                                      forMainFrameOnly:NO];
    [userContentController addUserScript:cookieScript];
    
    // 一下兩個屬性是允許H5視屏自動播放,并且全屏,可忽略
    configuration.allowsInlineMediaPlayback = YES;
    configuration.mediaPlaybackRequiresUserAction = NO;
    // 全局使用同一個processPool
    configuration.processPool = [[WKWebKitSupport sharedSupport] processPool];
    configuration.userContentController = userContentController;

#### 2.保存到本地
    // 在收到響應后,決定是否跳轉<br>
    -(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{

        NSLog(@"%@",navigationResponse.response.URL.absoluteString);
        NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
        // 獲取cookie,并設置到本地
        NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
        for (NSHTTPCookie *cookie in cookies) {
            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
        }

        //允許跳轉
        decisionHandler(WKNavigationResponsePolicyAllow);
        //不允許跳轉
        //decisionHandler(WKNavigationResponsePolicyCancel);
    }

 #### 3.在開始請求時注入

    NSURL *url = [NSURL URLWithString:urlString];
    NSMutableString *cookies = [NSMutableString string];
    NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];

    // 一般都只需要同步JSESSIONID,可視不同需求自己做更改
    NSString * JSESSIONID;
    // 獲取本地所有的Cookie
    NSArray *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
        for (NSHTTPCookie * cookie in tmp) {
            if ([cookie.name isEqualToString:@"JSESSIONID"]) {
                JSESSIONID = cookie.value;
                break;
            }
        }
     if (JSESSIONID.length) {
          // 格式化Cookie
          [cookies appendFormat:@"JSESSIONID=%@;",JSESSIONID];
      }
    // 注入Cookie
    [requestObj setValue:cookies forHTTPHeaderField:@"Cookie"];
    // 加載請求
    [self.wk_webView loadRequest:requestObj];

新增撥打電話和彈窗

    // 在發送請求之前,決定是否跳轉<br>
    -(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{

        NSLog(@"%@",navigationAction.request.URL.absoluteString);
        // 撥打電話

        NSURL *URL = navigationAction.request.URL;
        NSString *scheme = [URL scheme];
        UIApplication *app = [UIApplication sharedApplication];
        // 打電話
        if ([scheme isEqualToString:@"tel"]) {
            if ([app canOpenURL:URL]) {
                [app openURL:URL];
                // 一定要加上這句,否則會打開新頁面
                decisionHandler(WKNavigationActionPolicyCancel);
                return;
            }
        }
        // 打開appstore
        if ([URL.absoluteString containsString:@"ituns.apple.com"]) {
            if ([app canOpenURL:URL]) {
                [app openURL:URL];
                decisionHandler(WKNavigationActionPolicyCancel);
                return;
            }
        }

        //允許跳轉
        decisionHandler(WKNavigationActionPolicyAllow);
        //不允許跳轉
        //decisionHandler(WKNavigationActionPolicyCancel);
    }

    #### 警告框
    -(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{

        NSLog(@"%@",message);
        //  js 里面的alert實現,如果不實現,網頁的alert函數無效  ,
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
            completionHandler();
        }]];
        [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){
            completionHandler();
        }]];

        [self presentViewController:alertController animated:YES completion:^{}];
        // 要實現
    //    completionHandler();
    }

    #### 確認框

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

        //  js 里面的alert實現,如果不實現,網頁的alert函數無效  ,
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
        [alertController addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
            completionHandler(YES);
        }]];
        [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action){
            completionHandler(NO);
        }]];

        [self presentViewController:alertController animated:YES completion:^{}];

    }

適配HTML5頁面的問題

    // 內容視圖自適應大小
    NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
    WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
    [userContentController addUserScript:wkUScript];
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 為何使用WKWebView App開發過程中不可避免的會用到加載網頁,從iOS2開始,我們一直使用的是UIWebV...
    辰牧殤閱讀 1,013評論 0 1
  • Starting in iOS 8.0 and OS X 10.10, use WKWebView to add ...
    笑忘書丶閱讀 3,033評論 0 3
  • 隨說 : 最近有個需求,是將公司的一個內網的頁面嵌套在app中作為一個模塊.這不是很簡單的webView請求一下就...
    travin閱讀 30,945評論 26 73
  • 現在大部分的app只支持iOS8以上的系統了,在接入H5時可以只管最新的WKWebView了。 WKWebView...
    L小杰閱讀 17,353評論 6 33
  • 前言 關于UIWebView的介紹,相信看過上文的小伙伴們,已經大概清楚了吧,如果有問題,歡迎提問。 本文是本系列...
    CoderLF閱讀 9,022評論 2 12