要點:1.isEqualToString的使用
? ? ? ? ?2.NSURL與字符串的轉(zhuǎn)換比較
? ? ? ?問題:用一個webView加載一個html邮偎,html先是有一段文字和圖片乐疆,再有就是此html內(nèi)嵌了一個iframe吠冤,iframe里面有另外一個連接(比如一個視頻連接),這時候用webView去加載這個html砚尽,假如這個iframe里的視頻連接是錯誤的,加載不了梦碗,會報錯,這就會觸發(fā)webView的代理方法didFailLoadWithError,但是此html的連接是沒有問題的洪规,可以正常加載到文字和圖片印屁。這時候,如果我們需要在didFailLoadWithError方法里添加一個errorView 來提示加載出錯斩例,那么就會出現(xiàn)這樣的情況:盡管html連接沒有錯雄人,文字圖片也加載出來了,但是由于iframe里的連接出錯念赶,也會觸發(fā)didFailLoadWithError從而彈出我們設定的errorView础钠,進而阻止我們操作頁面,如下圖:
? ? ? 但是實際上我們想要的結(jié)果是這樣的:只要文字和圖片加載出來了叉谜,即使視頻無法加載旗吁,也不要彈出“加載失敗”這個框,只有當文字都加載不成功時才需要彈出這樣一個框停局,那么這時個就要找出哪個連接加載失敗哪個加載成功了很钓,進而作出選擇性地在相應連接出錯時才彈出錯誤窗口。
經(jīng)過打印跟蹤可以發(fā)現(xiàn)董栽,在webView的代理方法:shouldStartLoadWithRequest? 里码倦,會先后順序地加載請求連接,就是說在此方法里的request先會是加載html里的連接(就是webView loadRequest:url 中的這個連接)锭碳,再順序地加載到html里的iframe/src/js/css等的連接叹洲,那么這樣就可以在didFailLoadWithError方法里拿到加載出錯的連接來與這個html的url對比了,如果出錯的連接是這個url就讓他彈框工禾,如果不是就不用彈。
解決辦法:
定一個全局可變數(shù)組: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轉(zhuǎn)成NSString
if ([firstRequestUrl[0] isEqualToString:[failLoadUrlString absoluteString]]) {
? ? ? ?NSLog(@"兩個字符串相等,所以出錯的是第一個html的連接");
? ? ? ?//這時候就可以在這里寫彈出框了
}else{
? ? ? ?NSLog(@"兩個字符串不相等癣丧,就說明出錯的有可能是html里面的連接");
? ? ? //這時候就可以在這里隱藏彈框了
}
做完這一步槽畔,實際上上面的問題已經(jīng)解決,無論一個頁面內(nèi)含有多少個iframe胁编,iframe里面含有多少個鏈接厢钧,不管這些鏈接錯誤與否,只要出錯的鏈接不是這個頁面的主鏈接(第一個鏈接)嬉橙,那么就不會彈出錯誤提示框了早直。
但新的問題來了:
當我們用webView去加載一個電腦版的網(wǎng)址時,比如:http://www.qq.com/,這時在shouldStartLoadWithRequest代理方法中申請請求的url為http://www.qq.com/,但在請求過程中市框,會自動轉(zhuǎn)換成觸屏版的網(wǎng)址霞扬,即:http://xw.qq.com/index.htm,這時候,在failDidLoad方法中會監(jiān)測到錯誤鏈接:http://www.qq.com,且為第一個,但實際上整個請求頁面是可以實現(xiàn)的喻圃。如果按照上面的寫法萤彩,則會出現(xiàn)如下情況,且在有彈出框的情況下頁面是不可控的:
那么就不能按上面的寫法了斧拍,這時候可以這樣解決:
在shouldStartLoadWithRequest里計數(shù)請求的鏈接數(shù)count1雀扶,比如上面的qq.com請求過程中,由于會自動轉(zhuǎn)換成觸屏版的鏈接肆汹,所以實際上在這個代理方法中申請請求的鏈接個數(shù)為2個愚墓,可以打NSLog看到。
然后在FailDidLoad里再計數(shù)失敗的鏈接數(shù)count2,如上面的例子县踢,這里的count2個數(shù)為1转绷;
將count1 與 count2 比較,如果相等硼啤,彈框议经,如果不相等,忽略錯誤谴返,不彈框煞肾,意為整個請求頁面中只要有一個鏈接請求正確都不彈框;用這個方法代替上面的方法嗓袱,既可以避免頁面帶iframe且iframe里有錯誤鏈接時導致彈框籍救,又可以避免請求網(wǎng)址為電腦版時自動轉(zhuǎn)換為觸屏版時導致彈框這兩個問題。
暫時沒有測試到其他情況渠抹,大家發(fā)現(xiàn)的話請幫忙提出進行修改蝙昙。