iOS中UIWebView的一個需求:獲得js圖片請求完成的回調時機

來源:互聯網
上載者:User

標籤:

不久之前,項目中用到了UIWebView載入js的功能,之前使用webView都是簡單使用,沒考慮很多與js互動的地方,雖然現在項目完成了,但是回頭看看這方面的知識還是有些茫然,在此記錄一點,然後後續如果有用更多的話再來進行補充。

需求

封裝個view,提供給開發人員使用,暴露兩個方法以供調用:

1、是調用initWithXXX進行初始化位置等等參數配置;

2、調用loadH5PageWithSuccessBlock:failureBlock:讓view中的webView載入H5頁面顯示出來即可。

其主要實現就是webView載入一個URL的過程,給開發人員一個載入失敗和完成的回調。

 

UIWebView的代理方法

1、首先實現的是UIWebView的shouldStartLoadWithRequest:navigationType:代理方法 

註:對於返回的是unicode編碼的字串,用 stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding 進行返回UTF8編碼的字串。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {        NSLog(@"URL : %@", [request.URL.absoluteString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]);        // click event    if ([request.URL.host isEqualToString:@"call_close"])    {// notify click close        if (self.gh_clickCloseBlock) {            self.gh_clickCloseBlock(webView, request.URL.absoluteString);        }        [self stopTimer:self.loadStatusCheckTimer];        return NO;    }        if ([request.URL.host isEqualToString:@"on_click"])    {        NSString *URL_String = [request.URL.path substringFromIndex:1];        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:URL_String]];                // notify click content        if (self.gh_clickBlock) {            self.gh_clickBlock(webView, URL_String);        }        return NO;    }        return YES;}

如果上述回調中返回YES,那麼webView會進行載入html頁面,執行 webViewDidStartLoad: 回調。

每次在頁面中的點擊都可能會“截獲”該URL,並會再次調用上述回調,那麼通過URL的scheme和host就可以判斷是什麼動作事件,

例如:

如果是host為“call_close”,則可以做一些關閉的操作:移除view,停止定時器等,並添加關閉頁面的block回調給開發人員。

如果是host為“on_click”,則可以添加點擊頁面內容的block回調給開發人員。

 

2、開始載入的回調

- (void)webViewDidStartLoad:(UIWebView *)webView {    NSLog(@"start, %d", webView.loading);}

 

3、如果載入失敗的話會調用 didFailLoadWithError:

頁面載入逾時等失敗的時機回調給開發人員,但是對於請求中HTTP的狀態代碼error的時候並不能判斷出來,

對於這部分具體可以用NSURLConnection判斷response的statusCode,如果是400以上即可回調失敗,如果是成功響應再允許webView載入這個URL,

我們可以只要response,不需要receiveData,所以在得到response之後將connection cancel掉。

參考相關:http://stackoverflow.com/questions/1061364/how-do-i-get-the-last-http-status-code-from-a-uiwebview

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {    NSLog(@"failure : %@", error.description);        // page載入失敗的callBack    if (self.gh_loadFailBlock) {        self.gh_loadFailBlock(webView, error.code);    }}

 

4、page載入完成的回調,啟動定時器進行檢查,不斷擷取js中關於image的載入狀態,以便擷取回調時機。

- (void)webViewDidFinishLoad:(UIWebView *)webView {    NSLog(@"finish, %d", webView.loading);        [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect=‘none‘;"];    [webView stringByEvaluatingJavaScriptFromString:@"document.body.style.webkitTouchCallout=‘none‘;"];        if(!injectedPageLoadedJS)    {        injectedPageLoadedJS = YES;        [self stopTimer:self.loadStatusCheckTimer];        self.loadStatusCheckTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(checkLoadStatus:) userInfo:nil repeats:YES];    }}

載入html的時候,我們的js會執行對url進行請求的操作,其中會有請求image資源,但是在webView這裡,當html這個page載入完成時就會調用finish回調,如果載入H5頁面的成功回調寫在這裡,可能會出現js還沒有成功請求到圖片資源渲染到頁面上,你已經回調開發人員載入成功。所以期間從finish到image非同步請求完成,中間有段時間需要等待。

解決方式是在頁面載入完成finish之後,通過NSTimer不斷地去擷取js載入image狀態的傳回值,直到擷取成功的傳回值,做出給開發人員的block。

與js簡單互動

和前端協商將js中標示image非同步請求成功的變數定為window.__loadImageStatus__; 這樣js在拿到image請求成功的回調之後,會將此變數賦值為imgLoaded,這個js的值可以通過webView的stringByEvaluatingJavaScriptFromString:方法的傳回值拿到。 

何時去取到這個值,需要在webView載入完html頁面時finish回調之後取,可以添加一個定時器,每隔0.5s中通過stringByEvaluatingJavaScriptFromString:拿到傳回值,判斷是否是imgLoaded,如果是,說明此時圖片非同步載入成功,圖片已經展示,在此可以作為給開發人員的成功回調。

 

- (void)checkLoadStatus:(NSTimer *)timer {        NSString *evalString = [_webH5View stringByEvaluatingJavaScriptFromString:@"window.__loadImageStatus__;"];    NSLog(@"+++++js 返回的status值:%@", evalString);        if([evalString isEqualToString:@"imgLoaded"])    {        //Web page has finished. Shut down the timer.        [self stopTimer:timer];        injectedPageLoadedJS = NO;                NSLog(@"成功擷取到imgLoaded,js將image load 完成的回調值發給");// 成功回調        if (self.gh_loadAdSuccessBlock) {            self.gh_loadAdSuccessBlock(_webH5View, _request.URL.absoluteString);        }                self.count = 0;    }        else {                if (self.count > 10) {            [self stopTimer:timer];                    } else {            self.count += 1;        }    }}

 

註:最好添加一個計數器,當10次(也就是5s)還沒有擷取到js關於image載入成功的傳回值,就可以將timer等相關對象移除,避免長時間等待,影響互動體驗。

iOS中UIWebView的一個需求:獲得js圖片請求完成的回調時機

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.