WKWebview替代UIWebView之簡單攻略

前言

Xcode8發(fā)布以后,編譯器開始不支持IOS7东揣,所以很多應(yīng)用在適配IOS10之后都不在適配IOS7了践惑,其中包括了很多大公司,網(wǎng)易新聞嘶卧,滴滴出行等尔觉。因此,我們公司的應(yīng)用也打算淘汰IOS7芥吟。

支持到IOS8侦铜,第一個(gè)要改的自然是用WKWebView替換原來的UIWebView。WKWebView有很多明顯優(yōu)勢:

更多的支持HTML5的特性

官方宣稱的高達(dá)60fps的滾動(dòng)刷新率以及內(nèi)置手勢

將UIWebViewDelegate與UIWebView拆分成了14類與3個(gè)協(xié)議,以前很多不方便實(shí)現(xiàn)的功能得以實(shí)現(xiàn)运沦。文檔

Safari相同的JavaScript引擎

占用更少的內(nèi)存

UIWebView

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

UIWebView

WKWebView

WKWebView

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

基本使用方法

WKWebView有兩個(gè)delegate,WKUIDelegate和WKNavigationDelegate携添。WKNavigationDelegate主要處理一些跳轉(zhuǎn)、加載處理操作篓叶,WKUIDelegate主要處理JS腳本烈掠,確認(rèn)框,警告框等缸托。因此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

// 頁面開始加載時(shí)調(diào)用

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{}

// 當(dāng)內(nèi)容開始返回時(shí)調(diào)用

- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{}

// 頁面加載完成之后調(diào)用

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{}

// 頁面加載失敗時(shí)調(diào)用

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{}

// 接收到服務(wù)器跳轉(zhuǎn)請求之后調(diào)用

- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{}

// 在收到響應(yīng)后,決定是否跳轉(zhuǎn)

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void(^)(WKNavigationResponsePolicy))decisionHandler{NSLog(@"%@",navigationResponse.response.URL.absoluteString);//允許跳轉(zhuǎn)decisionHandler(WKNavigationResponsePolicyAllow);//不允許跳轉(zhuǎn)//decisionHandler(WKNavigationResponsePolicyCancel);}

// 在發(fā)送請求之前俐镐,決定是否跳轉(zhuǎn)

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler{NSLog(@"%@",navigationAction.request.URL.absoluteString);//允許跳轉(zhuǎn)decisionHandler(WKNavigationActionPolicyAllow);//不允許跳轉(zhuǎn)//decisionHandler(WKNavigationActionPolicyCancel);}

#pragma mark - WKUIDelegate

// 創(chuàng)建一個(gè)新的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");}

// 確認(rèn)框

- (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實(shí)現(xiàn)js交互 不需要借助JavaScriptCore或者webJavaScriptBridge矫限。使用WKUserContentController實(shí)現(xiàn)js native交互。簡單的說就是先注冊約定好的方法,然后再調(diào)用叼风。

JS調(diào)用OC方法

oc代碼(有誤取董,內(nèi)存不釋放):

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

@implementationViewController

#pragma mark - lifeCircle

- (void)viewDidLoad {? ? [superviewDidLoad];//配置環(huán)境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"];//注冊一個(gè)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代碼如果認(rèn)證測試一下就會(huì)發(fā)現(xiàn)dealloc并不會(huì)執(zhí)行茵汰,這樣肯定是不行的,會(huì)造成內(nèi)存泄漏孽鸡。原因是[userContentController addScriptMessageHandler:self name:@"sayhello"];這句代碼造成無法釋放內(nèi)存蹂午。(ps:試了下用weak指針還是不能釋放,不知道是什么原因彬碱。)因此還需要進(jìn)一步改進(jìn)豆胸,正確的寫法是用一個(gè)新的controller來處理,新的controller再繞用delegate繞回來。

functionsay(){//前端需要用 window.webkit.messageHandlers.注冊的方法名.postMessage({body:傳輸?shù)臄?shù)據(jù)} 來給native發(fā)送消息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/ }>

注意點(diǎn)

addScriptMessageHandler要和removeScriptMessageHandlerForName配套出現(xiàn)堡妒,否則會(huì)造成內(nèi)存泄漏配乱。

h5只能傳一個(gè)參數(shù),如果需要多個(gè)參數(shù)就需要用字典或者json組裝皮迟。

oc調(diào)用JS方法

代碼如下:

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

h5代碼同上。

WebViewJavascriptBridge

一般來說伏尼,一個(gè)好的UI總有一個(gè)大神會(huì)開發(fā)出一個(gè)好的第三方封裝框架忿檩。WebViewJavascriptBridge的作者也做了一套支持WKWebView與JS交互的第三方框架:WKWebViewJavascriptBridge。

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

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

主要方法如下:

//初始化方法

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

+ (void)enableLogging;

//注冊函數(shù)名

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

//調(diào)用函數(shù)名

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

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

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

//重置

- (void)reset;

//設(shè)置WKNavigationDelegate

- (void)setWebViewDelegate:(id)webViewDelegate;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末爆阶,一起剝皮案震驚了整個(gè)濱河市燥透,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辨图,老刑警劉巖班套,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異故河,居然都是意外死亡吱韭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門鱼的,熙熙樓的掌柜王于貴愁眉苦臉地迎上來理盆,“玉大人,你說我怎么就攤上這事凑阶≡彻妫” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵宙橱,是天一觀的道長姨俩。 經(jīng)常有香客問我蘸拔,道長,這世上最難降的妖魔是什么环葵? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任都伪,我火速辦了婚禮,結(jié)果婚禮上积担,老公的妹妹穿的比我還像新娘陨晶。我一直安慰自己,他們只是感情好帝璧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布先誉。 她就那樣靜靜地躺著,像睡著了一般的烁。 火紅的嫁衣襯著肌膚如雪褐耳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天渴庆,我揣著相機(jī)與錄音铃芦,去河邊找鬼。 笑死襟雷,一個(gè)胖子當(dāng)著我的面吹牛刃滓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耸弄,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼咧虎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了计呈?” 一聲冷哼從身側(cè)響起砰诵,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捌显,沒想到半個(gè)月后茁彭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扶歪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年理肺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片击罪。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哲嘲,死狀恐怖贪薪,靈堂內(nèi)的尸體忽然破棺而出媳禁,到底是詐尸還是另有隱情,我是刑警寧澤画切,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布竣稽,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏毫别。R本人自食惡果不足惜娃弓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岛宦。 院中可真熱鬧台丛,春花似錦、人聲如沸砾肺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽变汪。三九已至侠坎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間裙盾,已是汗流浹背实胸。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留番官,地道東北人庐完。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像徘熔,于是被迫代替她去往敵國和親假褪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 2016-10-26o翻滾的牛寶寶oCocoaChina ▲點(diǎn)擊上方“CocoaChina”關(guān)注即可免費(fèi)學(xué)習(xí)iOS...
  • 1近顷、加載網(wǎng)頁 WKWebView *webView = [[WKWebView alloc] initWithFr...
    LearningCoding閱讀 3,108評(píng)論 0 2
  • 前言 關(guān)于UIWebView的介紹生音,相信看過上文的小伙伴們,已經(jīng)大概清楚了吧窒升,如果有問題缀遍,歡迎提問。 本文是本系列...
    CoderLF閱讀 8,968評(píng)論 2 12
  • 前言: web頁面和app的直接的交互是很常見的東西饱须,在ios8之前域醇,用的是uiwebview,但是在ios8之后...
    qingchen91閱讀 2,955評(píng)論 6 25
  • 雪花蝕染的窗臺(tái)蓉媳,宛若隆冬里的湖譬挚,潤含深邃的心潮,定格在歲月的深處酪呻,寧靜而淡薄减宣。 記憶里的印痕,宛如一杯茶玩荠,透著隱...
    君遺墨閱讀 233評(píng)論 0 3