webView加載多個連接時判斷是否是第一個連接失敗

要點:1.isEqualToString的使用

? ? ? ? ?2.NSURL與字符串的轉換比較




? ? ? ?問題:用一個webView加載一個html,html先是有一段文字和圖片,再有就是此html內嵌了一個iframe,iframe里面有另外一個連接(比如一個視頻連接),這時候用webView去加載這個html,假如這個iframe里的視頻連接是錯誤的,加載不了,會報錯,這就會觸發webView的代理方法didFailLoadWithError,但是此html的連接是沒有問題的,可以正常加載到文字和圖片。這時候,如果我們需要在didFailLoadWithError方法里添加一個errorView 來提示加載出錯,那么就會出現這樣的情況:盡管html連接沒有錯,文字圖片也加載出來了,但是由于iframe里的連接出錯,也會觸發didFailLoadWithError從而彈出我們設定的errorView,進而阻止我們操作頁面,如下圖:

一個無錯誤頁面內含有一個錯誤鏈接的iframe


? ? ? 但是實際上我們想要的結果是這樣的:只要文字和圖片加載出來了,即使視頻無法加載,也不要彈出“加載失敗”這個框,只有當文字都加載不成功時才需要彈出這樣一個框,那么這時個就要找出哪個連接加載失敗哪個加載成功了,進而作出選擇性地在相應連接出錯時才彈出錯誤窗口。


經過打印跟蹤可以發現,在webView的代理方法:shouldStartLoadWithRequest? 里,會先后順序地加載請求連接,就是說在此方法里的request先會是加載html里的連接(就是webView loadRequest:url 中的這個連接),再順序地加載到html里的iframe/src/js/css等的連接,那么這樣就可以在didFailLoadWithError方法里拿到加載出錯的連接來與這個html的url對比了,如果出錯的連接是這個url就讓他彈框,如果不是就不用彈。


解決辦法:


定一個全局可變數組:NSMutableArray *firstRequestUrl;

首先初始化一個webView

UIWebView *myWebView = [[UIWebView alloc]initWithFrame:self.view.bounds];

[myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"aaa://bbbbb"]]];

myWebView.delegate = self;

[self.view addSubview:myWebView];

然后在shouldStartLoadWithRequest方法里只允許他添加第一個url

NSString *webViewRequestUrl = request.URL.absoluteString;

if (firstRequestUrl == nil) {

? ? ? ?firstRequestUrl = [NSMutableArray arrayWithCapacity:1];

? ? ? ?if (firstRequestUrl.count == 0) {

? ? ? ? ? ? ? ?[firstRequestUrl addObject:webViewRequestUrl];

? ? ? ?}

}


然后在didFailLoadWithError方法里拿到出錯的url,

NSURL *failLoadUrlString = error.userInfo[@"NSErrorFailingURLKey"];

可以打印error看看里面都有什么,注意這里是NSURL,如果硬是寫成了下面這樣:

// NSString *failLoadUrlString = (NSString *)error.userInfo[@"NSErrorFailingURLKey"];

當查看failLoadUrlString屬性時仍然是NSURL類型的,這就不能與上面獲得的字符串比較了,所以在下面比較時要先將NSURL轉成NSString


if ([firstRequestUrl[0] isEqualToString:[failLoadUrlString absoluteString]]) {

? ? ? ?NSLog(@"兩個字符串相等,所以出錯的是第一個html的連接");

? ? ? ?//這時候就可以在這里寫彈出框了

}else{

? ? ? ?NSLog(@"兩個字符串不相等,就說明出錯的有可能是html里面的連接");

? ? ? //這時候就可以在這里隱藏彈框了

}


做完這一步,實際上上面的問題已經解決,無論一個頁面內含有多少個iframe,iframe里面含有多少個鏈接,不管這些鏈接錯誤與否,只要出錯的鏈接不是這個頁面的主鏈接(第一個鏈接),那么就不會彈出錯誤提示框了。

但新的問題來了:


當我們用webView去加載一個電腦版的網址時,比如:http://www.qq.com/,這時在shouldStartLoadWithRequest代理方法中申請請求的url為http://www.qq.com/,但在請求過程中,會自動轉換成觸屏版的網址,即:http://xw.qq.com/index.htm,這時候,在failDidLoad方法中會監測到錯誤鏈接:http://www.qq.com,且為第一個,但實際上整個請求頁面是可以實現的。如果按照上面的寫法,則會出現如下情況,且在有彈出框的情況下頁面是不可控的:

請求電腦版網址會自動跳轉觸屏版

那么就不能按上面的寫法了,這時候可以這樣解決:

在shouldStartLoadWithRequest里計數請求的鏈接數count1,比如上面的qq.com請求過程中,由于會自動轉換成觸屏版的鏈接,所以實際上在這個代理方法中申請請求的鏈接個數為2個,可以打NSLog看到。

然后在FailDidLoad里再計數失敗的鏈接數count2,如上面的例子,這里的count2個數為1;

將count1 與 count2 比較,如果相等,彈框,如果不相等,忽略錯誤,不彈框,意為整個請求頁面中只要有一個鏈接請求正確都不彈框;用這個方法代替上面的方法,既可以避免頁面帶iframe且iframe里有錯誤鏈接時導致彈框,又可以避免請求網址為電腦版時自動轉換為觸屏版時導致彈框這兩個問題。

暫時沒有測試到其他情況,大家發現的話請幫忙提出進行修改。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容