WKWebView 攔截URL


 

轉載: http://blog.csdn.net/u011619283/article/details/52135982
 
原創  2016年08月06日 14:00:08

在上篇文章中講述了使用UIWebView攔截URL的方式來處理JS與OC交互。 
由於UIWebView比較耗內存,性能上不太好,而蘋果在iOS 8中推出了WKWebView。 
同樣的用WKWebView也可以攔截URL,做JS 與OC交互。關於WKWebView與UIWebView的對比,大家請自動百度或者google。

打開百度網頁前 打開百度網頁后
UIWebView 內存47M
WKWebView 內存47M

WKWebView 攔截URL

WKWebView 與 UIWebView 攔截URL 的處理方式基本一樣。除了代理方法和WKWebView的使用不太一樣,關於WKWebView更詳盡的講解和用法,還是自行搜索學習,本文重點還是講解如何實現JS 與OC 互相調用。

提醒:WKWebView 是iOS 8 推出的WebKit.framework中的控件,只有app 不需要兼容iOS 7及以下的時候才可以使用。

先看動態效果圖:

1.創建WKWebView,加載本地HTML。

WKWebView的創建有幾點不同: 
* 1.初始化多了個configuration參數,當然這個參數我們也可以不傳,直接使用默認的設置就好。 
* 2.WKWebView的代理有兩個navigationDelegateUIDelegate。我們要攔截URL,就要通過navigationDelegate的一個代理方法來實現。如果在HTML中要使用alert等彈窗,就必須得實現UIDelegate的相應代理方法。 
* 3.在iOS 9之前,WKWebView加載本地HTML會有一些問題。(不能加載本地HTML,或者部分CSS/本地圖片加載不了等)

我這里創建WKWebView的示例代碼是這樣的:

    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    configuration.userContentController = [WKUserContentController new];          WKPreferences *preferences = [WKPreferences new];     preferences.javaScriptCanOpenWindowsAutomatically = YES;     preferences.minimumFontSize = 30.0;     configuration.preferences = preferences;     self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];       NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil];     NSURL *fileURL = [NSURL fileURLWithPath:urlStr];     [self.webView loadFileURL:fileURL allowingReadAccessToURL:fileURL];          self.webView.navigationDelegate = self;     [self.view addSubview:self.webView];

 

因為加載的本地HTML內容,跟上一篇UIWebView中介紹的HTML內容一樣,所以關於HTML中的內容就不再講解了。

2.攔截URL

使用WKNavigationDelegate中的代理方法,攔截自定義的URL來實現JS調用OC方法。

#pragma mark - WKNavigationDelegate - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {     NSURL *URL = navigationAction.request.URL;     NSString *scheme = [URL scheme];     if ([scheme isEqualToString:@"haleyaction"]) {         [self handleCustomAction:URL];         decisionHandler(WKNavigationActionPolicyCancel);         return;     }     decisionHandler(WKNavigationActionPolicyAllow); }

 

需要注意的是:

1.如果實現了這個代理方法,就必須得調用decisionHandler這個block,否則會導致app 崩潰。block參數是個枚舉類型,WKNavigationActionPolicyCancel代表取消加載,相當於UIWebView的代理方法return NO的情況;WKNavigationActionPolicyAllow代表允許加載,相當於UIWebView的代理方法中 return YES的情況。 
2.其他的關於為什么要統一設置scheme,在上一篇中講過。

關於如何區分執行不同的OC 方法,也與UIWebView的處理方式一樣,通過URL 的host 來區分執行不同的方法:

#pragma mark - private method - (void)handleCustomAction:(NSURL *)URL {     NSString *host = [URL host];     if ([host isEqualToString:@"scanClick"]) {         NSLog(@"掃一掃");     } else if ([host isEqualToString:@"shareClick"]) {         [self share:URL];     } else if ([host isEqualToString:@"getLocation"]) {         [self getLocation];     } else if ([host isEqualToString:@"setColor"]) {         [self changeBGColor:URL];     } else if ([host isEqualToString:@"payAction"]) {         [self payAction:URL];     } else if ([host isEqualToString:@"shake"]) {         [self shakeAction];     } else if ([host isEqualToString:@"goBack"]) {         [self goBack];     } }

 

3.OC 調用 JS 方法

JS 調用OC 方法后,有的操作可能需要將結果返回給JS。這時候就是OC 調用JS 方法的場景。 
WKWebView 提供了一個新的方法evaluateJavaScript:completionHandler:,實現OC 調用JS 等場景。

- (void)getLocation {     // 獲取位置信息          // 將結果返回給js     NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')",@"廣東省深圳市南山區學府路XXXX號"];     [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {         NSLog(@"%@----%@",result, error);     }]; }

 

evaluateJavaScript:completionHandler:沒有返回值,JS 執行成功還是失敗會在completionHandler 中返回。所以使用這個API 就可以避免執行耗時的JS,或者alert 導致界面卡住的問題。

4.WKWebView中使用彈窗

在上面提到,如果在WKWebView中使用alert、confirm 等彈窗,就得實現WKWebView的WKUIDelegate中相應的代理方法。 
例如,我在JS中要顯示alert 彈窗,就必須實現如下代理方法,否則alert 並不會彈出。

#pragma mark - WKUIDelegate - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {     UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];     [alert addAction:[UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {         completionHandler();     }]];          [self presentViewController:alert animated:YES completion:nil]; }

 

其中completionHandler這個block 一定得調用,至於在哪里調用,倒是無所謂,我們也可以寫在方法實現的第一行,或者最后一行。

示例工程地址:JS_OC_URL


免責聲明!

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



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