使用WKWebView替換UIWebView

來源:互聯網
上載者:User

標籤:baidu   nil   style   佔用   tor   UI   點擊   選擇   int   

筆者最近在iOS10的系統用 uiwebview 載入 串連的時候  直接崩潰。

這時需要用 最新的 wkwebview 替換 uiwebview

下面就介紹下相關內容  (來自連結:http://www.wangyangdev.com/2015/11/13/使用WKWebView替換UIWebView/)

開發App的過程中,常常會遇到在App內部載入網頁,通常用UIWebView載入。這個自iOS2開始使用的網頁載入器一直是開發的心病:載入速度慢,佔用記憶體多,最佳化困難。如果載入網頁多,還可能因為過量佔用記憶體而給系統kill掉。各種最佳化的方法效果也不那麼明顯(點擊查看常用最佳化方法)。

 

 

iOS8以後,蘋果推出了新架構Webkit,提供了替換UIWebView的組件WKWebView。各種UIWebView的問題沒有了,速度更快了,佔用記憶體少了,一句話,WKWebView是App內部載入網頁的最佳選擇!

先看下 WKWebView的特性:

  1. 在效能、穩定性、功能方面有很大提升(最直觀的體現就是載入網頁是佔用的記憶體,模擬器載入百度與開源中國網站時,WKWebView佔用23M,而UIWebView佔用85M);
  2. 允許JavaScript的Nitro庫載入並使用(UIWebView中限制);
  3. 支援了更多的HTML5特性;
  4. 高達60fps的滾動重新整理率以及內建手勢;
  5. 將UIWebViewDelegate與UIWebView重構成了14類與3個協議(查看蘋果官方文檔);

然後從以下幾個方面說下WKWebView的基本用法:

  1. 載入網頁
  2. 載入的狀態回調
  3. 新的WKUIDelegate協議
  4. 動態載入並運行JS代碼
  5. webView 執行JS代碼
  6. JS調用App註冊過的方法
一、載入網頁

載入網頁或HTML代碼的方式與UIWebView相同,程式碼範例如下:

 WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];[self.view addSubview:webView];
二、載入的狀態回調 (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;
三、新的 WKUIDelegate協議

這個協議主要用於WKWebView處理web介面的三種提示框(警告框、確認框、輸入框),下面是警告框的例子:

/** *  web介面中有彈出警告框時調用 * *  @param webView           實現該代理的webview *  @param message           警告框中的內容 *  @param frame             主視窗 *  @param completionHandler 警告框消失調用 */- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(void (^)())completionHandler;
四、動態載入並運行 JS代碼

用於在用戶端內部加入JS代碼,並執行,樣本如下:

// 圖片縮放的js代碼NSString *js = @"var count = document.images.length;for (var i = 0; i < count; i++) {var image = document.images[i];image.style.width=320;};window.alert(‘找到‘ + count + ‘張圖‘);";// 根據JS字串初始化WKUserScript對象WKUserScript *script = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];// 根據產生的WKUserScript對象,初始化WKWebViewConfigurationWKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];[config.userContentController addUserScript:script];_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];[_webView loadHTMLString:@"<head></head><imgea src=‘http://www.nsu.edu.cn/v/2014v3/img/background/3.jpg‘ />"baseURL:nil];[self.view addSubview:_webView];
五、webView 執行 JS代碼

使用者調用用JS寫過的代碼,一般指服務端開發的:

//javaScriptString是JS方法名,completionHandler是非同步回調block[self.webView evaluateJavaScript:javaScriptString completionHandler:completionHandler];
六、 JS調用App註冊過的方法

WKWebView裡面註冊供JS調用的方法,是通過WKUserContentController類下面的方法:

- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

scriptMessageHandler是代理回調,JS調用name方法後,OC會調用scriptMessageHandler指定的對象。

JS在調用OC註冊方法的時候要用下面的方式:

window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

注意,name(方法名)是放在中間的,messageBody只能是一個對象,如果要傳多個值,需要封裝成數組,或者字典。整個樣本如下:

//OC註冊供JS調用的方法[[_webView configuration].userContentController addScriptMessageHandler:self name:@"closeMe"];//OC在JS調用方法做的處理- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{    NSLog(@"JS 調用了 %@ 方法,傳回參數 %@",message.name,message.body);}//JS調用    window.webkit.messageHandlers.closeMe.postMessage(null);

如果你在selfdealloc打個斷點,會發現self沒有釋放!這顯然是不行的!Google後看到一種解決方案,如下:

@interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;@end@implementation WeakScriptMessageDelegate- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate{    self = [super init];    if (self) {        _scriptDelegate = scriptDelegate;    }    return self;}- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{    [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];}@end

思路是另外建立一個代理對象,然後通過代理對象回調指定的self

WKUserContentController *userContentController = [[WKUserContentController alloc] init];    [userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"closeMe"];

運行代碼,self釋放了,WeakScriptMessageDelegate卻沒有釋放啊啊啊!
還需在selfdealloc裡面 添加這樣一句代碼:

[[_webView configuration].userContentController removeScriptMessageHandlerForName:@"closeMe"];

OK,圓滿解決問題!

目前,大多數App需要支援iOS7以上的版本,而WKWebView只在iOS8後才能用,所以需要一個相容性方案,既iOS7下用UIWebView,iOS8後用WKWebView。這個庫提供了這種相容性方案:https://github.com/wangyangcc/IMYWebView

以上部分內容參考自:http://www.brighttj.com/ios/ios-wkwebview-new-features-and-use.html

 

使用WKWebView替換UIWebView

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.