WKWebview替代UIWebView之簡單攻略

前言

Xcode8發布以后,編譯器開始不支持IOS7,所以很多應用在適配IOS10之后都不在適配IOS7了,其中包括了很多大公司,網易新聞,滴滴出行等。因此,我們公司的應用也打算淘汰IOS7。

支持到IOS8,第一個要改的自然是用WKWebView替換原來的UIWebView。WKWebView有很多明顯優勢:

更多的支持HTML5的特性

官方宣稱的高達60fps的滾動刷新率以及內置手勢

將UIWebViewDelegate與UIWebView拆分成了14類與3個協議,以前很多不方便實現的功能得以實現。文檔

Safari相同的JavaScript引擎

占用更少的內存

UIWebView

functionsay(){//前端需要用 window.webkit.messageHandlers.注冊的方法名.postMessage({body:傳輸的數據} 來給native發送消息window.webkit.messageHandlers.sayhello.postMessage({body:'hello world!'});}

UIWebView

WKWebView

WKWebView

因此,使用WkWebview替換UIWebView還是很有必要的。

基本使用方法

WKWebView有兩個delegate,WKUIDelegate和WKNavigationDelegate。WKNavigationDelegate主要處理一些跳轉、加載處理操作,WKUIDelegate主要處理JS腳本,確認框,警告框等。因此WKNavigationDelegate更加常用。

比較常用的方法:

#pragma mark - lifeCircle

- (void)viewDidLoad {? ? [superviewDidLoad];? ? webView = [[WKWebView alloc]init];? ? [self.viewaddSubview:webView];? ? [webView mas_makeConstraints:^(MASConstraintMaker *make) {? ? ? ? make.left.equalTo(self.view);? ? ? ? make.right.equalTo(self.view);? ? ? ? make.top.equalTo(self.view);? ? ? ? make.bottom.equalTo(self.view);? ? }];? ? webView.UIDelegate=self;? ? webView.navigationDelegate=self;? ? [webView loadRequest:[NSURLRequestrequestWithURL:[NSURLURLWithString:@"http://www.baidu.com"]]];}

#pragma mark - 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);}

#pragma mark - 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:(nullableNSString*)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(NSString* __nullable result))completionHandler{? ? completionHandler(@"http");}

// 確認框

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(BOOLresult))completionHandler{? ? completionHandler(YES);}

// 警告框

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString*)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(void))completionHandler{NSLog(@"%@",message);? ? completionHandler();}

OC與JS交互

WKWebview提供了API實現js交互 不需要借助JavaScriptCore或者webJavaScriptBridge。使用WKUserContentController實現js native交互。簡單的說就是先注冊約定好的方法,然后再調用。

JS調用OC方法

oc代碼(有誤,內存不釋放):

@interfaceViewController(){? ? WKWebView * webView;? ? WKUserContentController* userContentController;}@end

@implementationViewController

#pragma mark - lifeCircle

- (void)viewDidLoad {? ? [superviewDidLoad];//配置環境WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];? ? userContentController =[[WKUserContentController alloc]init];? ? configuration.userContentController= userContentController;? ? webView = [[WKWebView alloc]initWithFrame:CGRectMake(0,0,100,100) configuration:configuration];//注冊方法[userContentController addScriptMessageHandler:selfname:@"sayhello"];//注冊一個name為sayhello的js方法[self.viewaddSubview:webView];? ? [webView mas_makeConstraints:^(MASConstraintMaker *make) {? ? ? ? make.left.equalTo(self.view);? ? ? ? make.right.equalTo(self.view);? ? ? ? make.top.equalTo(self.view);? ? ? ? make.bottom.equalTo(self.view);? ? }];? ? webView.UIDelegate=self;? ? webView.navigationDelegate=self;? ? [webView loadRequest:[NSURLRequestrequestWithURL:[NSURLURLWithString:@"http://www.test.com"]]];}

- (void)dealloc{//這里需要注意,前面增加過的方法一定要remove掉。[userContentController removeScriptMessageHandlerForName:@"sayhello"];}

#pragma mark - WKScriptMessageHandler

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);}

@end

上面的OC代碼如果認證測試一下就會發現dealloc并不會執行,這樣肯定是不行的,會造成內存泄漏。原因是[userContentController addScriptMessageHandler:self name:@"sayhello"];這句代碼造成無法釋放內存。(ps:試了下用weak指針還是不能釋放,不知道是什么原因。)因此還需要進一步改進,正確的寫法是用一個新的controller來處理,新的controller再繞用delegate繞回來。

functionsay(){//前端需要用 window.webkit.messageHandlers.注冊的方法名.postMessage({body:傳輸的數據} 來給native發送消息window.webkit.messageHandlers.sayhello.postMessage({body:'hello world!'});}

hello world

say hello

打印出的log:

name:sayhello body:{? ? body ="hello world!";} frameInfo: { URL: http://www.test.com/ }>

注意點

addScriptMessageHandler要和removeScriptMessageHandlerForName配套出現,否則會造成內存泄漏。

h5只能傳一個參數,如果需要多個參數就需要用字典或者json組裝。

oc調用JS方法

代碼如下:

- (void)webView:(WKWebView *)tmpWebView didFinishNavigation:(WKNavigation *)navigation{//say()是JS方法名,completionHandler是異步回調block[webView evaluateJavaScript:@"say()"completionHandler:^(id_Nullable result,NSError* _Nullable error) {NSLog(@"%@",result);? ? }];}

h5代碼同上。

WebViewJavascriptBridge

一般來說,一個好的UI總有一個大神會開發出一個好的第三方封裝框架。WebViewJavascriptBridge的作者也做了一套支持WKWebView與JS交互的第三方框架:WKWebViewJavascriptBridge。

cocoaPods:pod 'WebViewJavascriptBridge', '~> 5.0.5'

github地址:https://github.com/marcuswestin/WebViewJavascriptBridge

主要方法如下:

//初始化方法

+ (instancetype)bridgeForWebView:(WKWebView*)webView;

+ (void)enableLogging;

//注冊函數名

- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;

//調用函數名

- (void)callHandler:(NSString*)handlerName;

- (void)callHandler:(NSString*)handlerName data:(id)data;

- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;

//重置

- (void)reset;

//設置WKNavigationDelegate

- (void)setWebViewDelegate:(id)webViewDelegate;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,698評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,202評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,742評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,580評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,297評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,688評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,693評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,875評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,438評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,183評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,384評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,931評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,612評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,022評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,297評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,093評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,330評論 2 377

推薦閱讀更多精彩內容

  • 2016-10-26o翻滾的牛寶寶oCocoaChina ▲點擊上方“CocoaChina”關注即可免費學習iOS...
    啷里個啷里個啷個里個啷閱讀 1,328評論 0 1
  • 1、加載網頁 WKWebView *webView = [[WKWebView alloc] initWithFr...
    LearningCoding閱讀 3,139評論 0 2
  • 前言 關于UIWebView的介紹,相信看過上文的小伙伴們,已經大概清楚了吧,如果有問題,歡迎提問。 本文是本系列...
    CoderLF閱讀 9,007評論 2 12
  • 前言: web頁面和app的直接的交互是很常見的東西,在ios8之前,用的是uiwebview,但是在ios8之后...
    qingchen91閱讀 2,964評論 6 25
  • 雪花蝕染的窗臺,宛若隆冬里的湖,潤含深邃的心潮,定格在歲月的深處,寧靜而淡薄。 記憶里的印痕,宛如一杯茶,透著隱...
    君遺墨閱讀 237評論 0 3