如何準(zhǔn)確判斷 WebView 加載完成

正常情況下我們把處理網(wǎng)頁(yè)加載完畢的代碼放在 - (void)webViewDidFinishLoad:(UIWebView *)webView里权逗。但 WebViewDidFinishLoad 時(shí)網(wǎng)頁(yè)真的加載完了嗎荣茫?

官方文檔并沒(méi)有說(shuō)明 WebViewDidFinishLoad 到底在什么時(shí)候被調(diào)用,但事實(shí)證明在某些情況下 WebViewDidFinishLoad 可能不是你想要的時(shí)機(jī)。

網(wǎng)頁(yè)重定向

當(dāng)網(wǎng)頁(yè)重定向發(fā)生時(shí)头滔,網(wǎng)址被重定向幾次嗅回,WebViewDidFinishLoad 就會(huì)被調(diào)用幾次。所以如果你只想在最后加載完成時(shí)調(diào)用某些代碼肝箱,可以通過(guò)webView.isLoading來(lái)判斷哄褒。當(dāng) WebViewDidFinishLoad 時(shí)如果 webView.isLoading == YES 那么說(shuō)明網(wǎng)頁(yè)可能發(fā)生了重定向。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (!webView.isLoading) {
        [self webViewDidFinishLoadCompletely];
    }
}

加載內(nèi)嵌資源

除了原生方法外煌张,網(wǎng)頁(yè)的 readyState 屬性也可以返回當(dāng)前加載狀態(tài)呐赡,共有5種。

  1. uninitialized : 還沒(méi)開(kāi)始加載
  2. loading : 加載中
  3. loaded : 加載完成
  4. interactive : 結(jié)束渲染唱矛,用戶(hù)已經(jīng)可以與網(wǎng)頁(yè)進(jìn)行交互罚舱。但內(nèi)嵌資源還在加載中
  5. complete : 完全加載完成

WebViewDidFinishLoad 被調(diào)用時(shí),readyState 可能處在 interactive 和 complete 兩種狀態(tài)绎谦。當(dāng)我們需要對(duì)網(wǎng)頁(yè)中的元素進(jìn)行修改時(shí)管闷,最好在 complete 狀態(tài)進(jìn)行,不然我們的修改可能被重置窃肠。例如百度登錄頁(yè)(http://wappass.baidu.com/passport) 在iPad上打開(kāi)時(shí)包个,WebViewDidFinishLoad 的 readyState 就是 interactive,這時(shí)如果修改輸入框里內(nèi)容(賬號(hào)密碼自動(dòng)填充)冤留,我們的修改將會(huì)在 complete 狀態(tài)時(shí)被重置碧囊。

為了解決這個(gè)問(wèn)題,我們可以在 WebViewDidFinishLoad 判斷 readyState 的狀態(tài)纤怒,如果不是 complete糯而,則重寫(xiě) window.onload 或者 document.onreadystatechange 兩個(gè)方法,他們都可以準(zhǔn)確判斷內(nèi)嵌資源加載完畢的時(shí)機(jī)泊窘。然后通過(guò) JSExport 回調(diào) Objective-C 代碼(如果是 WKWebView 則通過(guò) MessageHandler 回調(diào))熄驼。對(duì) JSExport 還不熟悉可以參考 這篇博客 來(lái)簡(jiǎn)單了解 JSExport 的使用。

- (void)webViewDidStartLoad:(UIWebView *)webView {
    _jsContext = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    _jsContext[@"xfNewsContext"] = _jsExport;
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (!webView.isLoading) {
        NSString *readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
        BOOL complete = [readyState isEqualToString:@"complete"];
        if (complete) {
            [self webViewDidFinishLoadCompletely];
        } else {
            NSString *jsString =
            @"window.onload = function() {"
            @"    xfNewsContext.onload();"
            @"};"
            @"document.onreadystatechange = function () {"
            @"    if (document.readyState == \"complete\") {"
            @"        xfNewsContext.documentReadyStateComplete();"
            @"    }"
            @"};";
            [_webView stringByEvaluatingJavaScriptFromString:jsString];
        }
        NSLog(@"%@", NSStringFromSelector(_cmd));
    }
}

- (void)onload {
    [self webViewDidFinishLoadCompletely];
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

- (void)documentReadyStateComplete {
    [self webViewDidFinishLoadCompletely];
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

- (void)webViewDidFinishLoadCompletely {
    [self displayContent];
}

在普通網(wǎng)頁(yè)加載時(shí)打印結(jié)果是:

  1. documentReadyStateComplete
  2. onload
  3. webViewDidFinishLoad:

而本例中打印結(jié)果則是:

  1. webViewDidFinishLoad:
  2. documentReadyStateComplete
  3. onload

不管 webViewDidFinishLoad 在何時(shí)調(diào)用烘豹,webViewDidFinishLoadCompletely 都保證在加載完成的時(shí)候觸發(fā)瓜贾。

本文的完整代碼可以在 XFNewsContentDemo 中查看。本問(wèn)與上篇博客共用 Demo携悯,所以 Demo 中有大量與本篇不相關(guān)的代碼祭芦。你只需要找到上述引用代碼的部分查看即可。

參考資料

[MDN] document.readyState
[w3schools] HTML DOM readyState Property
[CNBlogs]iOS判斷UIWebView加載完成的方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末憔鬼,一起剝皮案震驚了整個(gè)濱河市龟劲,隨后出現(xiàn)的幾起案子胃夏,更是在濱河造成了極大的恐慌,老刑警劉巖咸灿,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件构订,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡避矢,警方通過(guò)查閱死者的電腦和手機(jī)悼瘾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)审胸,“玉大人亥宿,你說(shuō)我怎么就攤上這事∩芭妫” “怎么了烫扼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)碍庵。 經(jīng)常有香客問(wèn)我映企,道長(zhǎng),這世上最難降的妖魔是什么静浴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任堰氓,我火速辦了婚禮,結(jié)果婚禮上苹享,老公的妹妹穿的比我還像新娘双絮。我一直安慰自己,他們只是感情好得问,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布囤攀。 她就那樣靜靜地躺著,像睡著了一般宫纬。 火紅的嫁衣襯著肌膚如雪焚挠。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天漓骚,我揣著相機(jī)與錄音宣蔚,去河邊找鬼。 笑死认境,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挟鸠。 我是一名探鬼主播叉信,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼艘希!你這毒婦竟也來(lái)了硼身?” 一聲冷哼從身側(cè)響起硅急,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎佳遂,沒(méi)想到半個(gè)月后营袜,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丑罪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年荚板,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吩屹。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡跪另,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出煤搜,到底是詐尸還是另有隱情免绿,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布擦盾,位于F島的核電站嘲驾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏迹卢。R本人自食惡果不足惜辽故,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望婶希。 院中可真熱鬧榕暇,春花似錦、人聲如沸喻杈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)筒饰。三九已至缴啡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓷们,已是汗流浹背业栅。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谬晕,地道東北人碘裕。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像攒钳,于是被迫代替她去往敵國(guó)和親帮孔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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